diff options
| author | HiFiPhile <[email protected]> | 2024-05-07 12:32:28 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-05-07 12:32:28 +0200 |
| commit | 4abdfc10f5a4cca19a614133655c64fec5752eb0 (patch) | |
| tree | f79aa084a42438667b5e26b588a6f794c9ad1608 /examples/device | |
| parent | 798ff807b3361a5859945cb23c3d0fd7d1a5679f (diff) | |
| parent | e5b6f93df35d7ac413ca405e67a6c9d8c79b680d (diff) | |
Merge branch 'master' into remove-tud_network_link_state_cb
Diffstat (limited to 'examples/device')
107 files changed, 7091 insertions, 615 deletions
diff --git a/examples/device/CMakeLists.txt b/examples/device/CMakeLists.txt index 0a2e49ef0..638440795 100644 --- a/examples/device/CMakeLists.txt +++ b/examples/device/CMakeLists.txt @@ -8,6 +8,8 @@ family_initialize_project(tinyusb_device_examples ${CMAKE_CURRENT_LIST_DIR}) # family_add_subdirectory will filter what to actually add based on selected FAMILY family_add_subdirectory(audio_4_channel_mic) family_add_subdirectory(audio_test) +family_add_subdirectory(audio_4_channel_mic_freertos) +family_add_subdirectory(audio_test_freertos) family_add_subdirectory(audio_test_multi_rate) family_add_subdirectory(board_test) family_add_subdirectory(cdc_dual_ports) @@ -28,4 +30,5 @@ family_add_subdirectory(net_lwip_webserver) family_add_subdirectory(uac2_headset) family_add_subdirectory(usbtmc) family_add_subdirectory(video_capture) +family_add_subdirectory(video_capture_2ch) family_add_subdirectory(webusb_serial) diff --git a/examples/device/audio_4_channel_mic/CMakeLists.txt b/examples/device/audio_4_channel_mic/CMakeLists.txt index f61e1b640..0f5d36193 100644 --- a/examples/device/audio_4_channel_mic/CMakeLists.txt +++ b/examples/device/audio_4_channel_mic/CMakeLists.txt @@ -28,6 +28,11 @@ target_include_directories(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) +# Add libm for GCC +if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_libraries(${PROJECT} PUBLIC m) +endif() + # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. family_configure_device_example(${PROJECT} noos) diff --git a/examples/device/audio_4_channel_mic/Makefile b/examples/device/audio_4_channel_mic/Makefile index 2a3d854fb..2c825bbf7 100644 --- a/examples/device/audio_4_channel_mic/Makefile +++ b/examples/device/audio_4_channel_mic/Makefile @@ -1,11 +1,14 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ $(TOP)/hw \ # Example source -EXAMPLE_SOURCE += $(wildcard src/*.c) +EXAMPLE_SOURCE += \ + src/main.c \ + src/usb_descriptors.c \ + SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/audio_4_channel_mic/skip.txt b/examples/device/audio_4_channel_mic/skip.txt index 1ee86a485..157605df1 100644 --- a/examples/device/audio_4_channel_mic/skip.txt +++ b/examples/device/audio_4_channel_mic/skip.txt @@ -1,3 +1,5 @@ mcu:SAMD11 mcu:SAME5X mcu:SAMG +family:broadcom_64bit +family:espressif diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index 94ac86d84..10e6fe88a 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -34,17 +34,16 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <math.h> #include "bsp/board_api.h" #include "tusb.h" +#include "tusb_config.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ - -#ifndef AUDIO_SAMPLE_RATE -#define AUDIO_SAMPLE_RATE 48000 -#endif +#define AUDIO_SAMPLE_RATE CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE /* Blink pattern * - 250 ms : device not mounted @@ -70,8 +69,13 @@ uint8_t clkValid; audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state -// Audio test data -uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ/2]; // Ensure half word aligned +#if CFG_TUD_AUDIO_ENABLE_ENCODING +// Audio test data, each buffer contains 2 channels, buffer[0] for CH0-1, buffer[1] for CH1-2 +uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX*CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE/1000/CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; +#else +// Audio test data, 4 channels muxed together, buffer[0] for CH0, buffer[1] for CH1, buffer[2] for CH2, buffer[3] for CH3 +uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX*CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE/1000]; +#endif void led_blinking_task(void); void audio_task(void); @@ -97,6 +101,45 @@ int main(void) sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE; sampleFreqRng.subrange[0].bRes = 0; + // Generate dummy data +#if CFG_TUD_AUDIO_ENABLE_ENCODING + uint16_t * p_buff = i2s_dummy_buffer[0]; + uint16_t dataVal = 0; + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) + { + // CH0 saw wave + *p_buff++ = dataVal; + // CH1 inverted saw wave + *p_buff++ = 3200 + AUDIO_SAMPLE_RATE/1000 - dataVal; + dataVal+= 32; + } + p_buff = i2s_dummy_buffer[1]; + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) + { + // CH3 square wave + *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 3400:5000; + // CH4 sinus wave + float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); + *p_buff++ = (uint16_t)((int16_t)(sinf(t) * 750) + 6000); + } +#else + uint16_t * p_buff = i2s_dummy_buffer; + uint16_t dataVal = 0; + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) + { + // CH0 saw wave + *p_buff++ = dataVal; + // CH1 inverted saw wave + *p_buff++ = 3200 + AUDIO_SAMPLE_RATE/1000 - dataVal; + dataVal+= 32; + // CH3 square wave + *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 3400:5000; + // CH4 sinus wave + float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); + *p_buff++ = (uint16_t)((int16_t)(sinf(t) * 750) + 6000); + } +#endif + while (1) { tud_task(); // tinyusb device task @@ -142,8 +185,21 @@ void tud_resume_cb(void) void audio_task(void) { - // Yet to be filled - e.g. put meas data into TX FIFOs etc. - // asm("nop"); + // Yet to be filled - e.g. read audio from I2S buffer. + // Here we simulate a I2S receive callback every 1ms. + static uint32_t start_ms = 0; + uint32_t curr_ms = board_millis(); + if ( start_ms == curr_ms ) return; // not enough time + start_ms = curr_ms; +#if CFG_TUD_AUDIO_ENABLE_ENCODING + // Write I2S buffer into FIFO + for (uint8_t cnt=0; cnt < 2; cnt++) + { + tud_audio_write_support_ff(cnt, i2s_dummy_buffer[cnt], AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX); + } +#else + tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); +#endif } //--------------------------------------------------------------------+ @@ -364,7 +420,8 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * { case AUDIO_CS_REQ_CUR: TU_LOG2(" Get Sample Freq.\r\n"); - return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); + // Buffered control transfer is needed for IN flow control to work + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); case AUDIO_CS_REQ_RANGE: TU_LOG2(" Get Sample Freq. range\r\n"); @@ -400,10 +457,14 @@ bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, u (void) ep_in; (void) cur_alt_setting; - for (uint8_t cnt=0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) - { - tud_audio_write_support_ff(cnt, i2s_dummy_buffer[cnt], AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX); - } + + // In read world application data flow is driven by I2S clock, + // both tud_audio_tx_done_pre_load_cb() & tud_audio_tx_done_post_load_cb() are hardly used. + // For example in your I2S receive callback: + // void I2S_Rx_Callback(int channel, const void* data, uint16_t samples) + // { + // tud_audio_write_support_ff(channel, data, samples * N_BYTES_PER_SAMPLE * N_CHANNEL_PER_FIFO); + // } return true; } @@ -416,22 +477,6 @@ bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uin (void) ep_in; (void) cur_alt_setting; - uint16_t dataVal; - - // Generate dummy data - for (uint16_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) - { - uint16_t * p_buff = i2s_dummy_buffer[cnt]; // 2 bytes per sample - dataVal = 1; - for (uint16_t cnt2 = 0; cnt2 < AUDIO_SAMPLE_RATE/1000; cnt2++) - { - for (uint8_t cnt3 = 0; cnt3 < CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX; cnt3++) - { - *p_buff++ = dataVal; - } - dataVal++; - } - } return true; } diff --git a/examples/device/audio_4_channel_mic/src/plot_audio_samples.py b/examples/device/audio_4_channel_mic/src/plot_audio_samples.py index 8312b4e28..d17a908b6 100644 --- a/examples/device/audio_4_channel_mic/src/plot_audio_samples.py +++ b/examples/device/audio_4_channel_mic/src/plot_audio_samples.py @@ -10,11 +10,11 @@ if __name__ == '__main__': # print(sd.query_devices()) fs = 48000 # Sample rate - duration = 100e-3 # Duration of recording + duration = 1 # Duration of recording if platform.system() == 'Windows': # WDM-KS is needed since there are more than one MicNode device APIs (at least in Windows) - device = 'Microphone (MicNode_4_Ch), Windows WDM-KS' + device = 'Microphone (MicNode_4_Ch), Windows WASAPI' elif platform.system() == 'Darwin': device = 'MicNode_4_Ch' else: @@ -25,9 +25,13 @@ if __name__ == '__main__': sd.wait() # Wait until recording is finished print('Done!') + time = np.arange(0, duration, 1 / fs) # time vector + # strip starting zero + plt.plot(time, myrecording) plt.xlabel('Time [s]') plt.ylabel('Amplitude') plt.title('MicNode 4 Channel') + plt.legend(['CH-1', 'CH-2', 'CH-3','CH-4']) plt.show() diff --git a/examples/device/audio_4_channel_mic/src/tusb_config.h b/examples/device/audio_4_channel_mic/src/tusb_config.h index 5cf6d07c3..46484f847 100644 --- a/examples/device/audio_4_channel_mic/src/tusb_config.h +++ b/examples/device/audio_4_channel_mic/src/tusb_config.h @@ -103,6 +103,7 @@ extern "C" { //-------------------------------------------------------------------- // Have a look into audio_device.h for all configurations +#define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000 #define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_FOUR_CH_DESC_LEN @@ -112,15 +113,27 @@ extern "C" { #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup -#define CFG_TUD_AUDIO_EP_SZ_IN (48 + 1) * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x CFG_TUD_AUDIO_N_CHANNELS_TX Channels - the Windows driver always needs an extra sample per channel of space more, otherwise it complains... found by trial and error +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) + +#define CFG_TUD_AUDIO_ENABLE_ENCODING 1 +#define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1 + +#if CFG_TUD_AUDIO_ENABLE_ENCODING + #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN -#define CFG_TUD_AUDIO_ENABLE_ENCODING 1 #define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 1 #define CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX 2 // One I2S stream contains two channels, each stream is saved within one support FIFO - this value is currently fixed, the driver does not support a changing value #define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX) -#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ (CFG_TUD_AUDIO_EP_SZ_IN / CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO) +#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * (CFG_TUD_AUDIO_EP_SZ_IN / CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO) // Example write FIFO every 1ms, so it should be 8 times larger for HS device + +#else + +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device + +#endif #ifdef __cplusplus } diff --git a/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt b/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt new file mode 100644 index 000000000..e8ca3751d --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.17) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) + +# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT} C CXX ASM) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() +endif() + +add_executable(${PROJECT}) + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/freertos_hook.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c + ) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + +# Add libm for GCC +if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_libraries(${PROJECT} PUBLIC m) +endif() + +# Configure compilation flags and libraries for the example with FreeRTOS. +# See the corresponding function in hw/bsp/FAMILY/family.cmake for details. +family_configure_device_example(${PROJECT} freertos) diff --git a/examples/device/audio_4_channel_mic_freertos/Makefile b/examples/device/audio_4_channel_mic_freertos/Makefile new file mode 100644 index 000000000..df2cdef4e --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/Makefile @@ -0,0 +1,38 @@ +include ../../build_system/make/make.mk + +FREERTOS_SRC = lib/FreeRTOS-Kernel +FREERTOS_PORTABLE_PATH = $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC) + +INC += \ + src \ + src/FreeRTOSConfig \ + $(TOP)/hw \ + $(TOP)/$(FREERTOS_SRC)/include \ + $(TOP)/$(FREERTOS_PORTABLE_SRC) \ + +# Example source +EXAMPLE_SOURCE = \ + src/freertos_hook.c \ + src/main.c \ + src/usb_descriptors.c + +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +# FreeRTOS source, all files in port folder +SRC_C += \ + $(FREERTOS_SRC)/list.c \ + $(FREERTOS_SRC)/queue.c \ + $(FREERTOS_SRC)/tasks.c \ + $(FREERTOS_SRC)/timers.c \ + $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.c)) + +SRC_S += \ + $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.s)) + +# Suppress FreeRTOS warnings +CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls + +# FreeRTOS (lto + Os) linker issue +LDFLAGS += -Wl,--undefined=vTaskSwitchContext + +include ../../build_system/make/rules.mk diff --git a/examples/device/audio_4_channel_mic_freertos/README.md b/examples/device/audio_4_channel_mic_freertos/README.md new file mode 100644 index 000000000..a99f28bc3 --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/README.md @@ -0,0 +1,19 @@ +# How to build example for Esp32s3 +1. Load idf environment variables (eg. using the esp-idf alias `get_idf` if configured) + +2. cd into examples directory +``` +$ cd /tinyusb/examples/device/audio_4_channel_mic_freertos +``` + +3. Run cmake in project directory specifying the board +``` +$ cmake -DBOARD=espressif_s3_devkitc -B build -G Ninja . +$ ninja.exe -C build +``` + +4. Flash the binary onto the esp32-s3 by copy-paste of the full command output by the esp-idf build system replacing **(PORT)** with eg. /dev/ttyUSB0 + +eg. + +> /home/kaspernyhus/.espressif/python_env/idf4.4_py3.8_env/bin/python ../../../../esp-idf/components/esptool_py/esptool/esptool.py -p /dev/ttyUSB0 -b 460800 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x0 _build/espressif_s3_devkitc/bootloader/bootloader.bin 0x8000 _build/espressif_s3_devkitc/partition_table/partition-table.bin 0x10000 _build/espressif_s3_devkitc/audio_4_channel_mic_freertos.bin diff --git a/examples/device/audio_4_channel_mic_freertos/sdkconfig.defaults b/examples/device/audio_4_channel_mic_freertos/sdkconfig.defaults new file mode 100644 index 000000000..eaa9fb902 --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/sdkconfig.defaults @@ -0,0 +1,4 @@ +CONFIG_IDF_CMAKE=y +CONFIG_FREERTOS_HZ=1000 +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt new file mode 100644 index 000000000..0b689192d --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/skip.txt @@ -0,0 +1,16 @@ +mcu:CH32V307 +mcu:CXD56 +mcu:F1C100S +mcu:GD32VF103 +mcu:MKL25ZXX +mcu:MSP430x5xx +mcu:RP2040 +mcu:SAMD11 +mcu:SAMX7X +mcu:VALENTYUSB_EPTRI +mcu:RAXXX +mcu:STM32L0 +board:lpcxpresso11u37 +board:lpcxpresso1347 +family:broadcom_32bit +family:broadcom_64bit diff --git a/examples/device/audio_4_channel_mic_freertos/src/CMakeLists.txt b/examples/device/audio_4_channel_mic_freertos/src/CMakeLists.txt new file mode 100644 index 000000000..cef2b46ee --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/src/CMakeLists.txt @@ -0,0 +1,4 @@ +# This file is for ESP-IDF only +idf_component_register(SRCS "main.c" "usb_descriptors.c" + INCLUDE_DIRS "." + REQUIRES boards tinyusb_src) diff --git a/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..6cc7a6577 --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,190 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + +// Include MCU header +#include "bsp/board_mcu.h" + +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 + #error "ESP32-Sx should use IDF's FreeRTOSConfig.h" +#endif + +// TODO fix later +#if CFG_TUSB_MCU == OPT_MCU_MM32F327X + extern u32 SystemCoreClock; +#else + // FIXME cause redundant-decls warnings + extern uint32_t SystemCoreClock; +#endif + +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE ( 1024 ) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*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 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 0 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +#ifdef __RX__ +/* Renesas RX series */ +#define vSoftwareInterruptISR INT_Excep_ICU_SWINT +#define vTickISR INT_Excep_CMT0_CMI0 +#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2) +#define configKERNEL_INTERRUPT_PRIORITY 1 +#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4 + +#else + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ +#if defined(__NVIC_PRIO_BITS) + // For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h + #define configPRIO_BITS __NVIC_PRIO_BITS + +#elif defined(__ECLIC_INTCTLBITS) + // RISC-V Bumblebee core from nuclei + #define configPRIO_BITS __ECLIC_INTCTLBITS + +#elif defined(__IASMARM__) + // FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS. + // Therefore we will hard coded it to minimum value of 2 to get pass ci build. + // IAR user must update this to correct value of the target MCU + #message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU" + #define configPRIO_BITS 2 + +#else + #error "FreeRTOS configPRIO_BITS to be defined" +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<<configPRIO_BITS) - 1) + +/* 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. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +#endif + +#endif /* __FREERTOS_CONFIG__H */ diff --git a/examples/device/audio_4_channel_mic_freertos/src/freertos_hook.c b/examples/device/audio_4_channel_mic_freertos/src/freertos_hook.c new file mode 100644 index 000000000..4920e3fae --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/src/freertos_hook.c @@ -0,0 +1,115 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.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 "FreeRTOS.h" +#include "task.h" +#include "common/tusb_common.h" + + +void vApplicationMallocFailedHook(void) +{ + taskDISABLE_INTERRUPTS(); + TU_ASSERT(false, ); +} + +void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName) +{ + (void) pxTask; + (void) pcTaskName; + + taskDISABLE_INTERRUPTS(); + TU_ASSERT(false, ); +} + +/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an + * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is + * used by the Idle task. */ +void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) +{ + /* If the buffers to be provided to the Idle task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xIdleTaskTCB; + static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Idle task's + state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; +} + +/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the + * application must provide an implementation of vApplicationGetTimerTaskMemory() + * to provide the memory that is used by the Timer service task. */ +void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) +{ + /* If the buffers to be provided to the Timer task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xTimerTaskTCB; + static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Timer + task's state will be stored. */ + *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; + + /* Pass out the array that will be used as the Timer task's stack. */ + *ppxTimerTaskStackBuffer = uxTimerTaskStack; + + /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */ + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +} + +#if CFG_TUSB_MCU == OPT_MCU_RX63X | CFG_TUSB_MCU == OPT_MCU_RX65X +#include "iodefine.h" +void vApplicationSetupTimerInterrupt(void) +{ + /* Enable CMT0 */ + unsigned short oldPRCR = SYSTEM.PRCR.WORD; + SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1); + MSTP(CMT0) = 0; + SYSTEM.PRCR.WORD = (0xA5u<<8) | oldPRCR; + + CMT0.CMCNT = 0; + CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128); + CMT0.CMCR.WORD = TU_BIT(6) | 2; + IR(CMT0, CMI0) = 0; + IPR(CMT0, CMI0) = configKERNEL_INTERRUPT_PRIORITY; + IEN(CMT0, CMI0) = 1; + CMT.CMSTR0.BIT.STR0 = 1; +} +#endif diff --git a/examples/device/audio_4_channel_mic_freertos/src/main.c b/examples/device/audio_4_channel_mic_freertos/src/main.c new file mode 100644 index 000000000..08f49326c --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/src/main.c @@ -0,0 +1,580 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Reinhard Panhuber + * + * 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. + * + */ + +/* plot_audio_samples.py requires following modules: + * $ sudo apt install libportaudio + * $ pip3 install sounddevice matplotlib + * + * Then run + * $ python3 plot_audio_samples.py + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> + +#include "bsp/board_api.h" +#include "tusb.h" + +#if TUP_MCU_ESPRESSIF + // ESP-IDF need "freertos/" prefix in include path. + // CFG_TUSB_OS_INC_PATH should be defined accordingly. + #include "freertos/FreeRTOS.h" + #include "freertos/semphr.h" + #include "freertos/queue.h" + #include "freertos/task.h" + #include "freertos/timers.h" + + #define USBD_STACK_SIZE 4096 +#else + + #include "FreeRTOS.h" + #include "semphr.h" + #include "queue.h" + #include "task.h" + #include "timers.h" + + // Increase stack size when debug log is enabled + #define USBD_STACK_SIZE (4*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) +#endif + +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define AUDIO_STACK_SIZE configMINIMAL_STACK_SIZE + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ +#define AUDIO_SAMPLE_RATE CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE + +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +// static task +#if configSUPPORT_STATIC_ALLOCATION +StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StaticTask_t blinky_taskdef; + +StackType_t usb_device_stack[USBD_STACK_SIZE]; +StaticTask_t usb_device_taskdef; + +StackType_t audio_stack[AUDIO_STACK_SIZE]; +StaticTask_t audio_taskdef; +#endif + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +// Audio controls +// Current states +bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint32_t sampFreq; +uint8_t clkValid; + +// Range states +audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state +audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state + +#if CFG_TUD_AUDIO_ENABLE_ENCODING +// Audio test data, each buffer contains 2 channels, buffer[0] for CH0-1, buffer[1] for CH1-2 +uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX*CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE/1000/CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; +#else +// Audio test data, 4 channels muxed together, buffer[0] for CH0, buffer[1] for CH1, buffer[2] for CH2, buffer[3] for CH3 +uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX*CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE/1000]; +#endif + +void led_blinking_task(void* param); +void usb_device_task(void* param); +void audio_task(void* param); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + // Init values + sampFreq = AUDIO_SAMPLE_RATE; + clkValid = 1; + + sampleFreqRng.wNumSubRanges = 1; + sampleFreqRng.subrange[0].bMin = AUDIO_SAMPLE_RATE; + sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE; + sampleFreqRng.subrange[0].bRes = 0; + + // Generate dummy data +#if CFG_TUD_AUDIO_ENABLE_ENCODING + uint16_t * p_buff = i2s_dummy_buffer[0]; + uint16_t dataVal = 0; + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) + { + // CH0 saw wave + *p_buff++ = dataVal; + // CH1 inverted saw wave + *p_buff++ = 3200 + AUDIO_SAMPLE_RATE/1000 - dataVal; + dataVal+= 32; + } + p_buff = i2s_dummy_buffer[1]; + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) + { + // CH3 square wave + *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 3400:5000; + // CH4 sinus wave + float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); + *p_buff++ = (uint16_t)((int16_t)(sinf(t) * 750) + 6000); + } +#else + uint16_t * p_buff = i2s_dummy_buffer; + uint16_t dataVal = 0; + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) + { + // CH0 saw wave + *p_buff++ = dataVal; + // CH1 inverted saw wave + *p_buff++ = 3200 + AUDIO_SAMPLE_RATE/1000 - dataVal; + dataVal+= 32; + // CH3 square wave + *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 3400:5000; + // CH4 sinus wave + float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); + *p_buff++ = (uint16_t)((int16_t)(sinf(t) * 750) + 6000); + } +#endif + +#if configSUPPORT_STATIC_ALLOCATION + // blinky task + xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); + + // Create a task for tinyusb device stack + xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); + + // Create a task for audio + xTaskCreateStatic(audio_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES-1, audio_stack, &audio_taskdef); +#else + xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + xTaskCreate(audio_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); +#endif + + // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 + #if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + vTaskStartScheduler(); + #endif + + return 0; +} + +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +void app_main(void) +{ + main(); +} +#endif + +// USB Device Driver task +// This top level thread process all usb events and invoke callbacks +void usb_device_task(void* param) +{ + (void) param; + + // init device stack on configured roothub port + // This should be called after scheduler/kernel is started. + // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tud_init(BOARD_TUD_RHPORT); + + if (board_init_after_tusb) { + board_init_after_tusb(); + } + + // RTOS forever loop + while (1) + { + // tinyusb device task + tud_task(); + } +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + blink_interval_ms = BLINK_NOT_MOUNTED; +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) +{ + (void) remote_wakeup_en; + blink_interval_ms = BLINK_SUSPENDED; +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) +{ + blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; +} + +//--------------------------------------------------------------------+ +// AUDIO Task +//--------------------------------------------------------------------+ + +void audio_task(void* param) +{ + (void) param; + // Yet to be filled - e.g. read audio from I2S buffer. + // Here we simulate a I2S receive callback every 1ms. + while (1) { + vTaskDelay(1); +#if CFG_TUD_AUDIO_ENABLE_ENCODING + // Write I2S buffer into FIFO + for (uint8_t cnt=0; cnt < 2; cnt++) + { + tud_audio_write_support_ff(cnt, i2s_dummy_buffer[cnt], AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX); + } +#else + tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); +#endif + } +} + +//--------------------------------------------------------------------+ +// Application Callback API Implementations +//--------------------------------------------------------------------+ + +// Invoked when audio class specific set request received for an EP +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + (void) pBuff; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) ep; + + return false; // Yet not implemented +} + +// Invoked when audio class specific set request received for an interface +bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + (void) pBuff; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) itf; + + return false; // Yet not implemented +} + +// Invoked when audio class specific set request received for an entity +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + (void) itf; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // If request is for our feature unit + if ( entityID == 2 ) + { + switch ( ctrlSel ) + { + case AUDIO_FU_CTRL_MUTE: + // Request uses format layout 1 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); + + mute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; + + TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); + return true; + + case AUDIO_FU_CTRL_VOLUME: + // Request uses format layout 2 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); + + volume[channelNum] = ((audio_control_cur_2_t*) pBuff)->bCur; + + TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); + return true; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an EP +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) ep; + + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an interface +bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) itf; + + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an entity +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + // uint8_t itf = TU_U16_LOW(p_request->wIndex); // Since we have only one audio function implemented, we do not need the itf value + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Input terminal (Microphone input) + if (entityID == 1) + { + switch ( ctrlSel ) + { + case AUDIO_TE_CTRL_CONNECTOR: + { + // The terminal connector control only has a get request with only the CUR attribute. + audio_desc_channel_cluster_t ret; + + // Those are dummy values for now + ret.bNrChannels = 1; + ret.bmChannelConfig = 0; + ret.iChannelNames = 0; + + TU_LOG2(" Get terminal connector\r\n"); + + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + } + break; + + // Unknown/Unsupported control selector + default: + TU_BREAKPOINT(); + return false; + } + } + + // Feature unit + if (entityID == 2) + { + switch ( ctrlSel ) + { + case AUDIO_FU_CTRL_MUTE: + // Audio control mute cur parameter block consists of only one byte - we thus can send it right away + // There does not exist a range parameter block for mute + TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); + + case AUDIO_FU_CTRL_VOLUME: + switch ( p_request->bRequest ) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); + + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); + + // Copy values - only for testing - better is version below + audio_control_range_2_n_t(1) + ret; + + ret.wNumSubRanges = 1; + ret.subrange[0].bMin = -90; // -90 dB + ret.subrange[0].bMax = 90; // +90 dB + ret.subrange[0].bRes = 1; // 1 dB steps + + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + + // Clock Source unit + if ( entityID == 4 ) + { + switch ( ctrlSel ) + { + case AUDIO_CS_CTRL_SAM_FREQ: + // channelNum is always zero in this case + switch ( p_request->bRequest ) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Sample Freq.\r\n"); + // Buffered control transfer is needed for IN flow control to work + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); + + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Sample Freq. range\r\n"); + return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; + + case AUDIO_CS_CTRL_CLK_VALID: + // Only cur attribute exists for this request + TU_LOG2(" Get Sample Freq. valid\r\n"); + return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + + TU_LOG2(" Unsupported entity: %d\r\n", entityID); + return false; // Yet not implemented +} + +bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) +{ + (void) rhport; + (void) itf; + (void) ep_in; + (void) cur_alt_setting; + + + // In read world application data flow is driven by I2S clock, + // both tud_audio_tx_done_pre_load_cb() & tud_audio_tx_done_post_load_cb() are hardly used. + // For example in your I2S receive callback: + // void I2S_Rx_Callback(int channel, const void* data, uint16_t samples) + // { + // tud_audio_write_support_ff(channel, data, samples * N_BYTES_PER_SAMPLE * N_CHANNEL_PER_FIFO); + // } + + return true; +} + +bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) +{ + (void) rhport; + (void) n_bytes_copied; + (void) itf; + (void) ep_in; + (void) cur_alt_setting; + + return true; +} + +bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + (void) p_request; + + return true; +} + +///--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +void led_blinking_task(void* param) { + (void) param; + static uint32_t start_ms = 0; + static bool led_state = false; + + while (1) { + // Blink every interval ms + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } +} diff --git a/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py b/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py new file mode 100644 index 000000000..8312b4e28 --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py @@ -0,0 +1,33 @@ +import sounddevice as sd +import matplotlib.pyplot as plt +import numpy as np +import platform + +if __name__ == '__main__': + + # If you got "ValueError: No input device matching", that is because your PC name example device + # differently from tested list below. Uncomment the next line to see full list and try to pick correct one + # print(sd.query_devices()) + + fs = 48000 # Sample rate + duration = 100e-3 # Duration of recording + + if platform.system() == 'Windows': + # WDM-KS is needed since there are more than one MicNode device APIs (at least in Windows) + device = 'Microphone (MicNode_4_Ch), Windows WDM-KS' + elif platform.system() == 'Darwin': + device = 'MicNode_4_Ch' + else: + device ='default' + + myrecording = sd.rec(int(duration * fs), samplerate=fs, channels=4, dtype='int16', device=device) + print('Waiting...') + sd.wait() # Wait until recording is finished + print('Done!') + + time = np.arange(0, duration, 1 / fs) # time vector + plt.plot(time, myrecording) + plt.xlabel('Time [s]') + plt.ylabel('Amplitude') + plt.title('MicNode 4 Channel') + plt.show() diff --git a/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h new file mode 100644 index 000000000..88f20278b --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h @@ -0,0 +1,148 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.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 _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Board Specific Configuration +//--------------------------------------------------------------------+ + +// RHPort number used for device can be defined by board.mk, default to port 0 +#ifndef BOARD_TUD_RHPORT +#define BOARD_TUD_RHPORT 0 +#endif + +// RHPort max operational speed can defined by board.mk +#ifndef BOARD_TUD_MAX_SPEED +#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU +#error CFG_TUSB_MCU must be defined +#endif + +// This examples use FreeRTOS +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_FREERTOS +#endif + +// Espressif IDF requires "freertos/" prefix in include path +#if TUP_MCU_ESPRESSIF +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG 0 +#endif + +// Enable Device stack +#define CFG_TUD_ENABLED 1 + +// Default is max speed that hardware controller could support with on-chip PHY +#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +#define CFG_TUD_AUDIO 1 +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_HID 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 + +//-------------------------------------------------------------------- +// AUDIO CLASS DRIVER CONFIGURATION +//-------------------------------------------------------------------- + +// Have a look into audio_device.h for all configurations +#define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000 + +#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_FOUR_CH_DESC_LEN + +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 +#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 + +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) + +#define CFG_TUD_AUDIO_ENABLE_ENCODING 1 +#define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1 + +#if CFG_TUD_AUDIO_ENABLE_ENCODING + +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN + +#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 1 +#define CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX 2 // One I2S stream contains two channels, each stream is saved within one support FIFO - this value is currently fixed, the driver does not support a changing value +#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX) +#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * (CFG_TUD_AUDIO_EP_SZ_IN / CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO) // Example write FIFO every 1ms, so it should be 8 times larger for HS device + +#else + +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c b/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c new file mode 100644 index 000000000..728a5f9ce --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c @@ -0,0 +1,179 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.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 "bsp/board_api.h" +#include "tusb.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + + // Use Interface Association Descriptor (IAD) for Audio + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ +enum +{ + ITF_NUM_AUDIO_CONTROL = 0, + ITF_NUM_AUDIO_STREAMING, + ITF_NUM_TOTAL +}; + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_FOUR_CH_DESC_LEN) + +#if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) + // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... + #define EPNUM_AUDIO 0x03 + +#elif TU_CHECK_MCU(OPT_MCU_NRF5X) + // nRF5x ISO can only be endpoint 8 + #define EPNUM_AUDIO 0x08 + +#else + #define EPNUM_AUDIO 0x01 +#endif + +uint8_t const desc_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) +}; + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + return desc_configuration; +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// String Descriptor Index +enum { + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, +}; + +// array of pointer to string descriptors +char const* string_desc_arr [] = { + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "PaniRCorp", // 1: Manufacturer + "MicNode_4_Ch", // 2: Product + NULL, // 3: Serials will use unique ID if possible + "UAC2", // 4: Audio Interface +}; + +static uint16_t _desc_str[32 + 1]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { + (void) langid; + size_t chr_count; + + switch ( index ) { + case STRID_LANGID: + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + break; + + case STRID_SERIAL: + chr_count = board_usb_get_serial(_desc_str + 1, 32); + break; + + default: + // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors + + if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + + const char *str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type + if ( chr_count > max_count ) chr_count = max_count; + + // Convert ASCII string into UTF-16 + for ( size_t i = 0; i < chr_count; i++ ) { + _desc_str[1 + i] = str[i]; + } + break; + } + + // first byte is length (including header), second byte is string type + _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); + + return _desc_str; +} diff --git a/examples/device/audio_test/Makefile b/examples/device/audio_test/Makefile index 2a3d854fb..7fa475da5 100644 --- a/examples/device/audio_test/Makefile +++ b/examples/device/audio_test/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -8,4 +8,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/audio_test/skip.txt b/examples/device/audio_test/skip.txt index 1ee86a485..65b137814 100644 --- a/examples/device/audio_test/skip.txt +++ b/examples/device/audio_test/skip.txt @@ -1,3 +1,4 @@ mcu:SAMD11 mcu:SAME5X mcu:SAMG +family:espressif diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 06783ccfb..f79bb4468 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -42,10 +42,6 @@ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -#ifndef AUDIO_SAMPLE_RATE -#define AUDIO_SAMPLE_RATE 48000 -#endif - /* Blink pattern * - 250 ms : device not mounted * - 1000 ms : device mounted @@ -90,12 +86,12 @@ int main(void) } // Init values - sampFreq = AUDIO_SAMPLE_RATE; + sampFreq = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; clkValid = 1; sampleFreqRng.wNumSubRanges = 1; - sampleFreqRng.subrange[0].bMin = AUDIO_SAMPLE_RATE; - sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE; + sampleFreqRng.subrange[0].bMin = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; + sampleFreqRng.subrange[0].bMax = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; sampleFreqRng.subrange[0].bRes = 0; while (1) diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index 9f38612a9..8c021e23c 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -106,6 +106,7 @@ extern "C" { //-------------------------------------------------------------------- // Have a look into audio_device.h for all configurations +#define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000 #define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_ONE_CH_DESC_LEN #define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) @@ -114,9 +115,9 @@ extern "C" { #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! -#define CFG_TUD_AUDIO_EP_SZ_IN (48 + 1) * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x CFG_TUD_AUDIO_N_CHANNELS_TX Channels - One extra sample is needed for asynchronous transfer adjustment, see feedback EP -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN // Maximum EP IN size for all AS alternate settings used -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN + 1 +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 8 : 1) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device #ifdef __cplusplus } diff --git a/examples/device/audio_test_freertos/CMakeLists.txt b/examples/device/audio_test_freertos/CMakeLists.txt new file mode 100644 index 000000000..eb22014fb --- /dev/null +++ b/examples/device/audio_test_freertos/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 3.17) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) + +# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT} C CXX ASM) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() +endif() + +add_executable(${PROJECT}) + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/freertos_hook.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c + ) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + +# Configure compilation flags and libraries for the example with FreeRTOS. +# See the corresponding function in hw/bsp/FAMILY/family.cmake for details. +family_configure_device_example(${PROJECT} freertos) diff --git a/examples/device/audio_test_freertos/Makefile b/examples/device/audio_test_freertos/Makefile new file mode 100644 index 000000000..df2cdef4e --- /dev/null +++ b/examples/device/audio_test_freertos/Makefile @@ -0,0 +1,38 @@ +include ../../build_system/make/make.mk + +FREERTOS_SRC = lib/FreeRTOS-Kernel +FREERTOS_PORTABLE_PATH = $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC) + +INC += \ + src \ + src/FreeRTOSConfig \ + $(TOP)/hw \ + $(TOP)/$(FREERTOS_SRC)/include \ + $(TOP)/$(FREERTOS_PORTABLE_SRC) \ + +# Example source +EXAMPLE_SOURCE = \ + src/freertos_hook.c \ + src/main.c \ + src/usb_descriptors.c + +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +# FreeRTOS source, all files in port folder +SRC_C += \ + $(FREERTOS_SRC)/list.c \ + $(FREERTOS_SRC)/queue.c \ + $(FREERTOS_SRC)/tasks.c \ + $(FREERTOS_SRC)/timers.c \ + $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.c)) + +SRC_S += \ + $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.s)) + +# Suppress FreeRTOS warnings +CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls + +# FreeRTOS (lto + Os) linker issue +LDFLAGS += -Wl,--undefined=vTaskSwitchContext + +include ../../build_system/make/rules.mk diff --git a/examples/device/audio_test_freertos/README.md b/examples/device/audio_test_freertos/README.md new file mode 100644 index 000000000..9477fcd78 --- /dev/null +++ b/examples/device/audio_test_freertos/README.md @@ -0,0 +1,19 @@ +# How to build example for Esp32s3 +1. Load idf environment variables (eg. using the esp-idf alias `get_idf` if configured) + +2. cd into examples directory +``` +$ cd /tinyusb/examples/device/audio_test_freertos +``` + +3. Run cmake in project directory specifying the board +``` +$ cmake -DBOARD=espressif_s3_devkitc -B build -G Ninja . +$ ninja.exe -C build +``` + +4. Flash the binary onto the esp32-s3 by copy-paste of the full command output by the esp-idf build system replacing **(PORT)** with eg. /dev/ttyUSB0 + +eg. + +> /home/kaspernyhus/.espressif/python_env/idf4.4_py3.8_env/bin/python ../../../../esp-idf/components/esptool_py/esptool/esptool.py -p /dev/ttyUSB0 -b 460800 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x0 _build/espressif_s3_devkitc/bootloader/bootloader.bin 0x8000 _build/espressif_s3_devkitc/partition_table/partition-table.bin 0x10000 _build/espressif_s3_devkitc/audio_test_freertos.bin diff --git a/examples/device/audio_test_freertos/sdkconfig.defaults b/examples/device/audio_test_freertos/sdkconfig.defaults new file mode 100644 index 000000000..83871619e --- /dev/null +++ b/examples/device/audio_test_freertos/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_IDF_CMAKE=y +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y diff --git a/examples/device/audio_test_freertos/skip.txt b/examples/device/audio_test_freertos/skip.txt new file mode 100644 index 000000000..a6f96b288 --- /dev/null +++ b/examples/device/audio_test_freertos/skip.txt @@ -0,0 +1,13 @@ +mcu:CH32V307 +mcu:CXD56 +mcu:F1C100S +mcu:GD32VF103 +mcu:MKL25ZXX +mcu:MSP430x5xx +mcu:RP2040 +mcu:SAMD11 +mcu:SAMX7X +mcu:VALENTYUSB_EPTRI +mcu:RAXXX +family:broadcom_32bit +family:broadcom_64bit diff --git a/examples/device/audio_test_freertos/src/CMakeLists.txt b/examples/device/audio_test_freertos/src/CMakeLists.txt new file mode 100644 index 000000000..cef2b46ee --- /dev/null +++ b/examples/device/audio_test_freertos/src/CMakeLists.txt @@ -0,0 +1,4 @@ +# This file is for ESP-IDF only +idf_component_register(SRCS "main.c" "usb_descriptors.c" + INCLUDE_DIRS "." + REQUIRES boards tinyusb_src) diff --git a/examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..6cc7a6577 --- /dev/null +++ b/examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,190 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + +// Include MCU header +#include "bsp/board_mcu.h" + +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 + #error "ESP32-Sx should use IDF's FreeRTOSConfig.h" +#endif + +// TODO fix later +#if CFG_TUSB_MCU == OPT_MCU_MM32F327X + extern u32 SystemCoreClock; +#else + // FIXME cause redundant-decls warnings + extern uint32_t SystemCoreClock; +#endif + +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE ( 1024 ) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*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 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 0 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +#ifdef __RX__ +/* Renesas RX series */ +#define vSoftwareInterruptISR INT_Excep_ICU_SWINT +#define vTickISR INT_Excep_CMT0_CMI0 +#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2) +#define configKERNEL_INTERRUPT_PRIORITY 1 +#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4 + +#else + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ +#if defined(__NVIC_PRIO_BITS) + // For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h + #define configPRIO_BITS __NVIC_PRIO_BITS + +#elif defined(__ECLIC_INTCTLBITS) + // RISC-V Bumblebee core from nuclei + #define configPRIO_BITS __ECLIC_INTCTLBITS + +#elif defined(__IASMARM__) + // FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS. + // Therefore we will hard coded it to minimum value of 2 to get pass ci build. + // IAR user must update this to correct value of the target MCU + #message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU" + #define configPRIO_BITS 2 + +#else + #error "FreeRTOS configPRIO_BITS to be defined" +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<<configPRIO_BITS) - 1) + +/* 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. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +#endif + +#endif /* __FREERTOS_CONFIG__H */ diff --git a/examples/device/audio_test_freertos/src/freertos_hook.c b/examples/device/audio_test_freertos/src/freertos_hook.c new file mode 100644 index 000000000..4920e3fae --- /dev/null +++ b/examples/device/audio_test_freertos/src/freertos_hook.c @@ -0,0 +1,115 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.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 "FreeRTOS.h" +#include "task.h" +#include "common/tusb_common.h" + + +void vApplicationMallocFailedHook(void) +{ + taskDISABLE_INTERRUPTS(); + TU_ASSERT(false, ); +} + +void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName) +{ + (void) pxTask; + (void) pcTaskName; + + taskDISABLE_INTERRUPTS(); + TU_ASSERT(false, ); +} + +/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an + * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is + * used by the Idle task. */ +void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) +{ + /* If the buffers to be provided to the Idle task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xIdleTaskTCB; + static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Idle task's + state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; +} + +/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the + * application must provide an implementation of vApplicationGetTimerTaskMemory() + * to provide the memory that is used by the Timer service task. */ +void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) +{ + /* If the buffers to be provided to the Timer task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xTimerTaskTCB; + static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Timer + task's state will be stored. */ + *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; + + /* Pass out the array that will be used as the Timer task's stack. */ + *ppxTimerTaskStackBuffer = uxTimerTaskStack; + + /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */ + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +} + +#if CFG_TUSB_MCU == OPT_MCU_RX63X | CFG_TUSB_MCU == OPT_MCU_RX65X +#include "iodefine.h" +void vApplicationSetupTimerInterrupt(void) +{ + /* Enable CMT0 */ + unsigned short oldPRCR = SYSTEM.PRCR.WORD; + SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1); + MSTP(CMT0) = 0; + SYSTEM.PRCR.WORD = (0xA5u<<8) | oldPRCR; + + CMT0.CMCNT = 0; + CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128); + CMT0.CMCR.WORD = TU_BIT(6) | 2; + IR(CMT0, CMI0) = 0; + IPR(CMT0, CMI0) = configKERNEL_INTERRUPT_PRIORITY; + IEN(CMT0, CMI0) = 1; + CMT.CMSTR0.BIT.STR0 = 1; +} +#endif diff --git a/examples/device/audio_test_freertos/src/main.c b/examples/device/audio_test_freertos/src/main.c new file mode 100644 index 000000000..a3751da40 --- /dev/null +++ b/examples/device/audio_test_freertos/src/main.c @@ -0,0 +1,508 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Reinhard Panhuber + * + * 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. + * + */ + +/* plot_audio_samples.py requires following modules: + * $ sudo apt install libportaudio + * $ pip3 install sounddevice matplotlib + * + * Then run + * $ python3 plot_audio_samples.py + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "bsp/board_api.h" +#include "tusb.h" + +#if TUP_MCU_ESPRESSIF + // ESP-IDF need "freertos/" prefix in include path. + // CFG_TUSB_OS_INC_PATH should be defined accordingly. + #include "freertos/FreeRTOS.h" + #include "freertos/semphr.h" + #include "freertos/queue.h" + #include "freertos/task.h" + #include "freertos/timers.h" + + #define USBD_STACK_SIZE 4096 +#else + + #include "FreeRTOS.h" + #include "semphr.h" + #include "queue.h" + #include "task.h" + #include "timers.h" + + // Increase stack size when debug log is enabled + #define USBD_STACK_SIZE (4*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) +#endif + +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ + +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +// static task +#if configSUPPORT_STATIC_ALLOCATION +StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StaticTask_t blinky_taskdef; + +StackType_t usb_device_stack[USBD_STACK_SIZE]; +StaticTask_t usb_device_taskdef; +#endif + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +// Audio controls +// Current states +bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint32_t sampFreq; +uint8_t clkValid; + +// Range states +audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state +audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state + +// Audio test data +uint16_t test_buffer_audio[(CFG_TUD_AUDIO_EP_SZ_IN - 2) / 2]; +uint16_t startVal = 0; + +void led_blinking_task(void* param); +void usb_device_task(void* param); +void audio_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + // Init values + sampFreq = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; + clkValid = 1; + + sampleFreqRng.wNumSubRanges = 1; + sampleFreqRng.subrange[0].bMin = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; + sampleFreqRng.subrange[0].bMax = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; + sampleFreqRng.subrange[0].bRes = 0; + +#if configSUPPORT_STATIC_ALLOCATION + // blinky task + xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); + + // Create a task for tinyusb device stack + xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); +#else + xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); +#endif + + // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 + #if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + vTaskStartScheduler(); + #endif + + return 0; +} + +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +void app_main(void) +{ + main(); +} +#endif + +// USB Device Driver task +// This top level thread process all usb events and invoke callbacks +void usb_device_task(void* param) +{ + (void) param; + + // init device stack on configured roothub port + // This should be called after scheduler/kernel is started. + // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tud_init(BOARD_TUD_RHPORT); + + if (board_init_after_tusb) { + board_init_after_tusb(); + } + + // RTOS forever loop + while (1) + { + // tinyusb device task + tud_task(); + } +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) { + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) { + blink_interval_ms = BLINK_NOT_MOUNTED; +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) { + (void) remote_wakeup_en; + blink_interval_ms = BLINK_SUSPENDED; +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) { + blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; +} + +//--------------------------------------------------------------------+ +// AUDIO Task +//--------------------------------------------------------------------+ + +void audio_task(void) +{ + // Yet to be filled - e.g. put meas data into TX FIFOs etc. + // asm("nop"); +} + +//--------------------------------------------------------------------+ +// Application Callback API Implementations +//--------------------------------------------------------------------+ + +// Invoked when audio class specific set request received for an EP +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + (void) pBuff; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) ep; + + return false; // Yet not implemented +} + +// Invoked when audio class specific set request received for an interface +bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + (void) pBuff; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) itf; + + return false; // Yet not implemented +} + +// Invoked when audio class specific set request received for an entity +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + (void) itf; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // If request is for our feature unit + if ( entityID == 2 ) + { + switch ( ctrlSel ) + { + case AUDIO_FU_CTRL_MUTE: + // Request uses format layout 1 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); + + mute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; + + TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); + return true; + + case AUDIO_FU_CTRL_VOLUME: + // Request uses format layout 2 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); + + volume[channelNum] = (uint16_t) ((audio_control_cur_2_t*) pBuff)->bCur; + + TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); + return true; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an EP +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) ep; + + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an interface +bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) itf; + + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an entity +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + // uint8_t itf = TU_U16_LOW(p_request->wIndex); // Since we have only one audio function implemented, we do not need the itf value + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Input terminal (Microphone input) + if (entityID == 1) + { + switch ( ctrlSel ) + { + case AUDIO_TE_CTRL_CONNECTOR: + { + // The terminal connector control only has a get request with only the CUR attribute. + audio_desc_channel_cluster_t ret; + + // Those are dummy values for now + ret.bNrChannels = 1; + ret.bmChannelConfig = (audio_channel_config_t) 0; + ret.iChannelNames = 0; + + TU_LOG2(" Get terminal connector\r\n"); + + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + } + break; + + // Unknown/Unsupported control selector + default: + TU_BREAKPOINT(); + return false; + } + } + + // Feature unit + if (entityID == 2) + { + switch ( ctrlSel ) + { + case AUDIO_FU_CTRL_MUTE: + // Audio control mute cur parameter block consists of only one byte - we thus can send it right away + // There does not exist a range parameter block for mute + TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); + + case AUDIO_FU_CTRL_VOLUME: + switch ( p_request->bRequest ) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); + + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); + + // Copy values - only for testing - better is version below + audio_control_range_2_n_t(1) + ret; + + ret.wNumSubRanges = 1; + ret.subrange[0].bMin = -90; // -90 dB + ret.subrange[0].bMax = 90; // +90 dB + ret.subrange[0].bRes = 1; // 1 dB steps + + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + + // Clock Source unit + if ( entityID == 4 ) + { + switch ( ctrlSel ) + { + case AUDIO_CS_CTRL_SAM_FREQ: + // channelNum is always zero in this case + switch ( p_request->bRequest ) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Sample Freq.\r\n"); + return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); + + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Sample Freq. range\r\n"); + return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; + + case AUDIO_CS_CTRL_CLK_VALID: + // Only cur attribute exists for this request + TU_LOG2(" Get Sample Freq. valid\r\n"); + return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + + TU_LOG2(" Unsupported entity: %d\r\n", entityID); + return false; // Yet not implemented +} + +bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) +{ + (void) rhport; + (void) itf; + (void) ep_in; + (void) cur_alt_setting; + + tud_audio_write ((uint8_t *)test_buffer_audio, CFG_TUD_AUDIO_EP_SZ_IN - 2); + + return true; +} + +bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) +{ + (void) rhport; + (void) n_bytes_copied; + (void) itf; + (void) ep_in; + (void) cur_alt_setting; + + for (size_t cnt = 0; cnt < (CFG_TUD_AUDIO_EP_SZ_IN - 2) / 2; cnt++) + { + test_buffer_audio[cnt] = startVal++; + } + + return true; +} + +bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + (void) p_request; + startVal = 0; + + return true; +} + +//--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +void led_blinking_task(void* param) { + (void) param; + static uint32_t start_ms = 0; + static bool led_state = false; + + while (1) { + // Blink every interval ms + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } +} diff --git a/examples/device/audio_test_freertos/src/plot_audio_samples.py b/examples/device/audio_test_freertos/src/plot_audio_samples.py new file mode 100644 index 000000000..304b2d5de --- /dev/null +++ b/examples/device/audio_test_freertos/src/plot_audio_samples.py @@ -0,0 +1,33 @@ +import sounddevice as sd +import matplotlib.pyplot as plt +import numpy as np +import platform + +if __name__ == '__main__': + + # If you got "ValueError: No input device matching", that is because your PC name example device + # differently from tested list below. Uncomment the next line to see full list and try to pick correct one + # print(sd.query_devices()) + + fs = 48000 # Sample rate + duration = 1000e-3 # Duration of recording + + if platform.system() == 'Windows': + # MME is needed since there are more than one MicNode device APIs (at least in Windows) + device = 'Microphone (MicNode) MME' + elif platform.system() == 'Darwin': + device = 'MicNode' + else: + device ='default' + + myrecording = sd.rec(int(duration * fs), samplerate=fs, channels=1, dtype='int16', device=device) + print('Waiting...') + sd.wait() # Wait until recording is finished + print('Done!') + + time = np.arange(0, duration, 1 / fs) # time vector + plt.plot(time, myrecording) + plt.xlabel('Time [s]') + plt.ylabel('Amplitude') + plt.title('MicNode') + plt.show() diff --git a/examples/device/audio_test_freertos/src/tusb_config.h b/examples/device/audio_test_freertos/src/tusb_config.h new file mode 100644 index 000000000..8b376a4c3 --- /dev/null +++ b/examples/device/audio_test_freertos/src/tusb_config.h @@ -0,0 +1,132 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.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 _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Board Specific Configuration +//--------------------------------------------------------------------+ + +// RHPort number used for device can be defined by board.mk, default to port 0 +#ifndef BOARD_TUD_RHPORT +#define BOARD_TUD_RHPORT 0 +#endif + +// RHPort max operational speed can defined by board.mk +#ifndef BOARD_TUD_MAX_SPEED +#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU +#error CFG_TUSB_MCU must be defined +#endif + +// This examples use FreeRTOS +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_FREERTOS +#endif + +// Espressif IDF requires "freertos/" prefix in include path +#if TUP_MCU_ESPRESSIF +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG 0 +#endif + +// Enable Device stack +#define CFG_TUD_ENABLED 1 + +// Default is max speed that hardware controller could support with on-chip PHY +#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +#define CFG_TUD_AUDIO 1 +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_HID 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 + +//-------------------------------------------------------------------- +// AUDIO CLASS DRIVER CONFIGURATION +//-------------------------------------------------------------------- + +// Have a look into audio_device.h for all configurations +#define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000 + +#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_ONE_CH_DESC_LEN +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) +#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 // Size of control request buffer + +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 8 : 1) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_test_freertos/src/usb_descriptors.c b/examples/device/audio_test_freertos/src/usb_descriptors.c new file mode 100644 index 000000000..9864377f6 --- /dev/null +++ b/examples/device/audio_test_freertos/src/usb_descriptors.c @@ -0,0 +1,181 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.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 "bsp/board_api.h" +#include "tusb.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + + // Use Interface Association Descriptor (IAD) for Audio + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ +enum +{ + ITF_NUM_AUDIO_CONTROL = 0, + ITF_NUM_AUDIO_STREAMING, + ITF_NUM_TOTAL +}; + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_ONE_CH_DESC_LEN) + +#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX + // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... + #define EPNUM_AUDIO 0x03 + +#elif TU_CHECK_MCU(OPT_MCU_NRF5X) + // nRF5x ISO can only be endpoint 8 + #define EPNUM_AUDIO 0x08 + +#else + #define EPNUM_AUDIO 0x01 +#endif + +uint8_t const desc_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) +}; + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + return desc_configuration; +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// String Descriptor Index +enum { + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, +}; + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "PaniRCorp", // 1: Manufacturer + "MicNode", // 2: Product + NULL, // 3: Serials will use unique ID if possible + "UAC2", // 4: Audio Interface + +}; + +static uint16_t _desc_str[32 + 1]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { + (void) langid; + size_t chr_count; + + switch ( index ) { + case STRID_LANGID: + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + break; + + case STRID_SERIAL: + chr_count = board_usb_get_serial(_desc_str + 1, 32); + break; + + default: + // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors + + if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + + const char *str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type + if ( chr_count > max_count ) chr_count = max_count; + + // Convert ASCII string into UTF-16 + for ( size_t i = 0; i < chr_count; i++ ) { + _desc_str[1 + i] = str[i]; + } + break; + } + + // first byte is length (including header), second byte is string type + _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); + + return _desc_str; +} diff --git a/examples/device/audio_test_multi_rate/Makefile b/examples/device/audio_test_multi_rate/Makefile index 2a3d854fb..7fa475da5 100644 --- a/examples/device/audio_test_multi_rate/Makefile +++ b/examples/device/audio_test_multi_rate/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -8,4 +8,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/audio_test_multi_rate/skip.txt b/examples/device/audio_test_multi_rate/skip.txt index 1ee86a485..65b137814 100644 --- a/examples/device/audio_test_multi_rate/skip.txt +++ b/examples/device/audio_test_multi_rate/skip.txt @@ -1,3 +1,4 @@ mcu:SAMD11 mcu:SAME5X mcu:SAMG +family:espressif diff --git a/examples/device/audio_test_multi_rate/src/main.c b/examples/device/audio_test_multi_rate/src/main.c index 3e7f40dac..2ff7f10bd 100644 --- a/examples/device/audio_test_multi_rate/src/main.c +++ b/examples/device/audio_test_multi_rate/src/main.c @@ -272,7 +272,7 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * sampFreq = (uint32_t)((audio_control_cur_4_t *)pBuff)->bCur; - TU_LOG2("Clock set current freq: %lu\r\n", sampFreq); + TU_LOG2("Clock set current freq: %" PRIu32 "\r\n", sampFreq); return true; break; diff --git a/examples/device/board_test/Makefile b/examples/device/board_test/Makefile index 2a3d854fb..7fa475da5 100644 --- a/examples/device/board_test/Makefile +++ b/examples/device/board_test/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -8,4 +8,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/board_test/src/main.c b/examples/device/board_test/src/main.c index 0a134a2e6..91799eb89 100644 --- a/examples/device/board_test/src/main.c +++ b/examples/device/board_test/src/main.c @@ -26,39 +26,31 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> - #include "bsp/board_api.h" -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTOTYPES -//--------------------------------------------------------------------+ - /* Blink pattern * - 250 ms : button is not pressed * - 1000 ms : button is pressed (and hold) */ -enum { +enum { BLINK_PRESSED = 250, BLINK_UNPRESSED = 1000 }; #define HELLO_STR "Hello from TinyUSB\r\n" -int main(void) -{ +int main(void) { board_init(); board_led_write(true); uint32_t start_ms = 0; bool led_state = false; - while (1) - { + while (1) { uint32_t interval_ms = board_button_read() ? BLINK_PRESSED : BLINK_UNPRESSED; // Blink and print every interval ms - if ( !(board_millis() - start_ms < interval_ms) ) - { + if (!(board_millis() - start_ms < interval_ms)) { board_uart_write(HELLO_STR, strlen(HELLO_STR)); start_ms = board_millis(); @@ -69,16 +61,14 @@ int main(void) // echo uint8_t ch; - if ( board_uart_read(&ch, 1) > 0 ) - { + if (board_uart_read(&ch, 1) > 0) { board_uart_write(&ch, 1); } } } #if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 -void app_main(void) -{ +void app_main(void) { main(); } #endif diff --git a/examples/device/board_test/src/tusb_config.h b/examples/device/board_test/src/tusb_config.h index 2c2eb5280..36eafe807 100644 --- a/examples/device/board_test/src/tusb_config.h +++ b/examples/device/board_test/src/tusb_config.h @@ -48,6 +48,11 @@ #define CFG_TUSB_OS OPT_OS_NONE #endif +// Espressif IDF requires "freertos/" prefix in include path +#if TUP_MCU_ESPRESSIF +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + // This example only test LED & GPIO, disable both device and host stack #define CFG_TUD_ENABLED 0 #define CFG_TUH_ENABLED 0 diff --git a/examples/device/cdc_dual_ports/Makefile b/examples/device/cdc_dual_ports/Makefile index 2a3d854fb..7fa475da5 100644 --- a/examples/device/cdc_dual_ports/Makefile +++ b/examples/device/cdc_dual_ports/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -8,4 +8,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/cdc_dual_ports/src/main.c b/examples/device/cdc_dual_ports/src/main.c index 98f3ab923..1167a5d50 100644 --- a/examples/device/cdc_dual_ports/src/main.c +++ b/examples/device/cdc_dual_ports/src/main.c @@ -31,12 +31,24 @@ #include "bsp/board_api.h" #include "tusb.h" -//------------- prototypes -------------// +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +static void led_blinking_task(void); static void cdc_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port @@ -46,28 +58,23 @@ int main(void) board_init_after_tusb(); } - while (1) - { + while (1) { tud_task(); // tinyusb device task cdc_task(); + led_blinking_task(); } } // echo to either Serial0 or Serial1 // with Serial0 as all lower case, Serial1 as all upper case -static void echo_serial_port(uint8_t itf, uint8_t buf[], uint32_t count) -{ +static void echo_serial_port(uint8_t itf, uint8_t buf[], uint32_t count) { uint8_t const case_diff = 'a' - 'A'; - for(uint32_t i=0; i<count; i++) - { - if (itf == 0) - { + for (uint32_t i = 0; i < count; i++) { + if (itf == 0) { // echo back 1st port as lower case if (isupper(buf[i])) buf[i] += case_diff; - } - else - { + } else { // echo back 2nd port as upper case if (islower(buf[i])) buf[i] -= case_diff; } @@ -77,21 +84,29 @@ static void echo_serial_port(uint8_t itf, uint8_t buf[], uint32_t count) tud_cdc_n_write_flush(itf); } +// Invoked when device is mounted +void tud_mount_cb(void) { + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) { + blink_interval_ms = BLINK_NOT_MOUNTED; +} + + //--------------------------------------------------------------------+ // USB CDC //--------------------------------------------------------------------+ -static void cdc_task(void) -{ +static void cdc_task(void) { uint8_t itf; - for (itf = 0; itf < CFG_TUD_CDC; itf++) - { + for (itf = 0; itf < CFG_TUD_CDC; itf++) { // connected() check for DTR bit // Most but not all terminal client set this when making connection // if ( tud_cdc_n_connected(itf) ) { - if ( tud_cdc_n_available(itf) ) - { + if (tud_cdc_n_available(itf)) { uint8_t buf[64]; uint32_t count = tud_cdc_n_read(itf, buf, sizeof(buf)); @@ -103,3 +118,18 @@ static void cdc_task(void) } } } + +//--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +void led_blinking_task(void) { + static uint32_t start_ms = 0; + static bool led_state = false; + + // Blink every interval ms + if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} diff --git a/examples/device/cdc_msc/Makefile b/examples/device/cdc_msc/Makefile index 429959e70..0c2e37180 100644 --- a/examples/device/cdc_msc/Makefile +++ b/examples/device/cdc_msc/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -12,4 +12,4 @@ EXAMPLE_SOURCE += \ SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/cdc_msc/skip.txt b/examples/device/cdc_msc/skip.txt index eadb6e74a..833fd072c 100644 --- a/examples/device/cdc_msc/skip.txt +++ b/examples/device/cdc_msc/skip.txt @@ -1 +1,2 @@ mcu:SAMD11 +family:espressif diff --git a/examples/device/cdc_msc/src/main.c b/examples/device/cdc_msc/src/main.c index 172f48ae0..4581a3bab 100644 --- a/examples/device/cdc_msc/src/main.c +++ b/examples/device/cdc_msc/src/main.c @@ -23,10 +23,6 @@ * */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - #include "bsp/board_api.h" #include "tusb.h" @@ -39,7 +35,7 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -51,8 +47,7 @@ void led_blinking_task(void); void cdc_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port @@ -62,8 +57,7 @@ int main(void) board_init_after_tusb(); } - while (1) - { + while (1) { tud_task(); // tinyusb device task led_blinking_task(); @@ -76,29 +70,25 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ +void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } @@ -106,15 +96,13 @@ void tud_resume_cb(void) //--------------------------------------------------------------------+ // USB CDC //--------------------------------------------------------------------+ -void cdc_task(void) -{ +void cdc_task(void) { // connected() check for DTR bit // Most but not all terminal client set this when making connection // if ( tud_cdc_connected() ) { // connected and there are data available - if ( tud_cdc_available() ) - { + if (tud_cdc_available()) { // read data char buf[64]; uint32_t count = tud_cdc_read(buf, sizeof(buf)); @@ -131,37 +119,32 @@ void cdc_task(void) } // Invoked when cdc when line state changed e.g connected/disconnected -void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) -{ +void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { (void) itf; (void) rts; // TODO set some indicator - if ( dtr ) - { + if (dtr) { // Terminal connected - }else - { + } else { // Terminal disconnected } } // Invoked when CDC interface received data from host -void tud_cdc_rx_cb(uint8_t itf) -{ +void tud_cdc_rx_cb(uint8_t itf) { (void) itf; } //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void) { static uint32_t start_ms = 0; static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/cdc_msc_freertos/Makefile b/examples/device/cdc_msc_freertos/Makefile index 0bee668b7..fe3fb6482 100644 --- a/examples/device/cdc_msc_freertos/Makefile +++ b/examples/device/cdc_msc_freertos/Makefile @@ -1,16 +1,14 @@ -DEPS_SUBMODULES += lib/FreeRTOS-Kernel - -include ../../make.mk +include ../../build_system/make/make.mk FREERTOS_SRC = lib/FreeRTOS-Kernel -FREERTOS_PORTABLE_PATH= $(FREERTOS_SRC)/portable/$(if $(USE_IAR),IAR,GCC) +FREERTOS_PORTABLE_PATH = $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC) INC += \ src \ src/FreeRTOSConfig \ $(TOP)/hw \ $(TOP)/$(FREERTOS_SRC)/include \ - $(TOP)/$(FREERTOS_PORTABLE_SRC) + $(TOP)/$(FREERTOS_PORTABLE_SRC) \ # Example source EXAMPLE_SOURCE = \ @@ -45,4 +43,4 @@ CFLAGS_GCC += -Wno-error=cast-qual # FreeRTOS (lto + Os) linker issue LDFLAGS_GCC += -Wl,--undefined=vTaskSwitchContext -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/cdc_msc_freertos/skip.txt b/examples/device/cdc_msc_freertos/skip.txt index a6f96b288..eb434c23b 100644 --- a/examples/device/cdc_msc_freertos/skip.txt +++ b/examples/device/cdc_msc_freertos/skip.txt @@ -9,5 +9,6 @@ mcu:SAMD11 mcu:SAMX7X mcu:VALENTYUSB_EPTRI mcu:RAXXX +mcu:STM32L0 family:broadcom_32bit family:broadcom_64bit diff --git a/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h index 69d638288..6cc7a6577 100644 --- a/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h +++ b/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h @@ -96,6 +96,7 @@ #define configUSE_TICK_HOOK 0 #define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning #define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 /* Run time and task stats gathering related definitions. */ #define configGENERATE_RUN_TIME_STATS 0 @@ -130,23 +131,6 @@ #define INCLUDE_xEventGroupSetBitFromISR 0 #define INCLUDE_xTimerPendFunctionCall 0 -/* Define to trap errors during development. */ -// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 -#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) - #define configASSERT(_exp) \ - do {\ - if ( !(_exp) ) { \ - volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ - if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ - taskDISABLE_INTERRUPTS(); \ - __asm("BKPT #0\n"); \ - }\ - }\ - } while(0) -#else - #define configASSERT( x ) -#endif - #ifdef __RX__ /* Renesas RX series */ #define vSoftwareInterruptISR INT_Excep_ICU_SWINT diff --git a/examples/device/cdc_msc_freertos/src/freertos_hook.c b/examples/device/cdc_msc_freertos/src/freertos_hook.c index ab885947c..4920e3fae 100644 --- a/examples/device/cdc_msc_freertos/src/freertos_hook.c +++ b/examples/device/cdc_msc_freertos/src/freertos_hook.c @@ -99,9 +99,10 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, Stack void vApplicationSetupTimerInterrupt(void) { /* Enable CMT0 */ + unsigned short oldPRCR = SYSTEM.PRCR.WORD; SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1); MSTP(CMT0) = 0; - SYSTEM.PRCR.WORD = (0xA5u<<8); + SYSTEM.PRCR.WORD = (0xA5u<<8) | oldPRCR; CMT0.CMCNT = 0; CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128); diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index 0b115a595..607d40270 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -30,7 +30,7 @@ #include "bsp/board_api.h" #include "tusb.h" -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF // ESP-IDF need "freertos/" prefix in include path. // CFG_TUSB_OS_INC_PATH should be defined accordingly. #include "freertos/FreeRTOS.h" @@ -41,6 +41,7 @@ #define USBD_STACK_SIZE 4096 #else + #include "FreeRTOS.h" #include "semphr.h" #include "queue.h" @@ -51,10 +52,11 @@ #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) #endif -#define CDC_STACK_SZIE configMINIMAL_STACK_SIZE +#define CDC_STACK_SIZE configMINIMAL_STACK_SIZE +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE //--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTYPES +// MACRO CONSTANT TYPEDEF PROTOTYPES //--------------------------------------------------------------------+ /* Blink pattern @@ -62,73 +64,69 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, }; -// static timer & task +// static task #if configSUPPORT_STATIC_ALLOCATION -StaticTimer_t blinky_tmdef; +StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StaticTask_t blinky_taskdef; StackType_t usb_device_stack[USBD_STACK_SIZE]; StaticTask_t usb_device_taskdef; -StackType_t cdc_stack[CDC_STACK_SZIE]; +StackType_t cdc_stack[CDC_STACK_SIZE]; StaticTask_t cdc_taskdef; #endif -TimerHandle_t blinky_tm; +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; -void led_blinky_cb(TimerHandle_t xTimer); -void usb_device_task(void* param); -void cdc_task(void* params); +static void usb_device_task(void *param); +void led_blinking_task(void* param); +void cdc_task(void *params); //--------------------------------------------------------------------+ // Main //--------------------------------------------------------------------+ -int main(void) -{ +int main(void) { board_init(); #if configSUPPORT_STATIC_ALLOCATION - // soft timer for blinky - blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); + // blinky task + xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); // Create a task for tinyusb device stack xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); // Create CDC task - xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); + xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, cdc_stack, &cdc_taskdef); #else - blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb); - xTaskCreate( usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL); - xTaskCreate( cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL); + xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + xTaskCreate(cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL); #endif - xTimerStart(blinky_tm, 0); - // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 -#if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if !TUP_MCU_ESPRESSIF vTaskStartScheduler(); #endif return 0; } -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -void app_main(void) -{ +#if TUP_MCU_ESPRESSIF +void app_main(void) { main(); } #endif // USB Device Driver task // This top level thread process all usb events and invoke callbacks -void usb_device_task(void* param) -{ +static void usb_device_task(void *param) { (void) param; // init device stack on configured roothub port @@ -141,8 +139,7 @@ void usb_device_task(void* param) } // RTOS forever loop - while (1) - { + while (1) { // put this thread to waiting state until there is new events tud_task(); @@ -156,56 +153,42 @@ void usb_device_task(void* param) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); +void tud_mount_cb(void) { + blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); +void tud_umount_cb(void) { + blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ +void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_SUSPENDED), 0); + blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ - if (tud_mounted()) - { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); - } - else - { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); - } +void tud_resume_cb(void) { + blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } //--------------------------------------------------------------------+ // USB CDC //--------------------------------------------------------------------+ -void cdc_task(void* params) -{ +void cdc_task(void *params) { (void) params; // RTOS forever loop - while ( 1 ) - { + while (1) { // connected() check for DTR bit // Most but not all terminal client set this when making connection // if ( tud_cdc_connected() ) { // There are data available - while ( tud_cdc_available() ) - { + while (tud_cdc_available()) { uint8_t buf[64]; // read and echo back @@ -228,35 +211,37 @@ void cdc_task(void* params) } // Invoked when cdc when line state changed e.g connected/disconnected -void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) -{ +void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { (void) itf; (void) rts; // TODO set some indicator - if ( dtr ) - { + if (dtr) { // Terminal connected - }else - { + } else { // Terminal disconnected } } // Invoked when CDC interface received data from host -void tud_cdc_rx_cb(uint8_t itf) -{ +void tud_cdc_rx_cb(uint8_t itf) { (void) itf; } //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinky_cb(TimerHandle_t xTimer) -{ - (void) xTimer; +void led_blinking_task(void* param) { + (void) param; + static uint32_t start_ms = 0; static bool led_state = false; - board_led_write(led_state); - led_state = 1 - led_state; // toggle + while (1) { + // Blink every interval ms + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } } diff --git a/examples/device/cdc_msc_freertos/src/msc_disk.c b/examples/device/cdc_msc_freertos/src/msc_disk.c index 9520dfec1..c8a04bb74 100644 --- a/examples/device/cdc_msc_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_freertos/src/msc_disk.c @@ -184,7 +184,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff uint8_t const* addr = msc_disk[lba] + offset; memcpy(buffer, addr, bufsize); - return bufsize; + return (int32_t) bufsize; } // Callback invoked when received WRITE10 command. @@ -203,7 +203,7 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* (void) lba; (void) offset; (void) buffer; #endif - return bufsize; + return (int32_t) bufsize; } // Callback invoked when received an SCSI command not in built-in list below @@ -237,14 +237,14 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, { if(in_xfer) { - memcpy(buffer, response, resplen); + memcpy(buffer, response, (size_t) resplen); }else { // SCSI output } } - return resplen; + return (int32_t) resplen; } #endif diff --git a/examples/device/cdc_msc_freertos/src/tusb_config.h b/examples/device/cdc_msc_freertos/src/tusb_config.h index 91efe7d40..e743c9148 100644 --- a/examples/device/cdc_msc_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_freertos/src/tusb_config.h @@ -59,7 +59,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/device/cdc_uac2/Makefile b/examples/device/cdc_uac2/Makefile index b7a8302ce..21dcdb0b2 100644 --- a/examples/device/cdc_uac2/Makefile +++ b/examples/device/cdc_uac2/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -13,4 +13,4 @@ EXAMPLE_SOURCE += \ SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/cdc_uac2/src/main.c b/examples/device/cdc_uac2/src/main.c index 7afa96c1a..25b2cd9a5 100644 --- a/examples/device/cdc_uac2/src/main.c +++ b/examples/device/cdc_uac2/src/main.c @@ -60,7 +60,7 @@ int main(void) led_blinking_task(); #if (CFG_TUSB_MCU == OPT_MCU_RP2040) - // printf("Hello, world!\n"); + // printf("Hello, world!\r\n"); #endif } diff --git a/examples/device/cdc_uac2/src/tusb_config.h b/examples/device/cdc_uac2/src/tusb_config.h index 373f0b01f..93489cf62 100644 --- a/examples/device/cdc_uac2/src/tusb_config.h +++ b/examples/device/cdc_uac2/src/tusb_config.h @@ -151,11 +151,11 @@ extern "C" { // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 -#define CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) -#define CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) +#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) +#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT) -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT) // Maximum EP IN size for all AS alternate settings used +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT) +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT) // Maximum EP IN size for all AS alternate settings used // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) #define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 2 diff --git a/examples/device/cdc_uac2/src/uac2_app.c b/examples/device/cdc_uac2/src/uac2_app.c index 98659ea68..c57d98a1a 100644 --- a/examples/device/cdc_uac2/src/uac2_app.c +++ b/examples/device/cdc_uac2/src/uac2_app.c @@ -69,7 +69,7 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t { if (request->bRequest == AUDIO_CS_REQ_CUR) { - TU_LOG1("Clock get current freq %lu\r\n", current_sample_rate); + TU_LOG1("Clock get current freq %" PRIu32 "\r\n", current_sample_rate); audio_control_cur_4_t curf = { (int32_t) tu_htole32(current_sample_rate) }; return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &curf, sizeof(curf)); @@ -118,7 +118,7 @@ static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t current_sample_rate = (uint32_t) ((audio_control_cur_4_t const *)buf)->bCur; - TU_LOG1("Clock set current freq: %ld\r\n", current_sample_rate); + TU_LOG1("Clock set current freq: %" PRIu32 "\r\n", current_sample_rate); return true; } diff --git a/examples/device/dfu/Makefile b/examples/device/dfu/Makefile index b3f2cc588..52a24cdb0 100644 --- a/examples/device/dfu/Makefile +++ b/examples/device/dfu/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -11,4 +11,4 @@ EXAMPLE_SOURCE = \ SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/dfu/skip.txt b/examples/device/dfu/skip.txt index 9ac346bad..9dde06c30 100644 --- a/examples/device/dfu/skip.txt +++ b/examples/device/dfu/skip.txt @@ -1,2 +1,3 @@ mcu:TM4C123 mcu:BCM2835 +family:espressif diff --git a/examples/device/dfu_runtime/Makefile b/examples/device/dfu_runtime/Makefile index da088ea6b..1b4d398cf 100644 --- a/examples/device/dfu_runtime/Makefile +++ b/examples/device/dfu_runtime/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -8,4 +8,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/dynamic_configuration/Makefile b/examples/device/dynamic_configuration/Makefile index da088ea6b..1b4d398cf 100644 --- a/examples/device/dynamic_configuration/Makefile +++ b/examples/device/dynamic_configuration/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -8,4 +8,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/dynamic_configuration/skip.txt b/examples/device/dynamic_configuration/skip.txt index eadb6e74a..833fd072c 100644 --- a/examples/device/dynamic_configuration/skip.txt +++ b/examples/device/dynamic_configuration/skip.txt @@ -1 +1,2 @@ mcu:SAMD11 +family:espressif diff --git a/examples/device/hid_boot_interface/Makefile b/examples/device/hid_boot_interface/Makefile index b3f2cc588..52a24cdb0 100644 --- a/examples/device/hid_boot_interface/Makefile +++ b/examples/device/hid_boot_interface/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -11,4 +11,4 @@ EXAMPLE_SOURCE = \ SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/hid_composite/Makefile b/examples/device/hid_composite/Makefile index da088ea6b..1b4d398cf 100644 --- a/examples/device/hid_composite/Makefile +++ b/examples/device/hid_composite/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -8,4 +8,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/hid_composite_freertos/Makefile b/examples/device/hid_composite_freertos/Makefile index a892e7d1d..88d602393 100644 --- a/examples/device/hid_composite_freertos/Makefile +++ b/examples/device/hid_composite_freertos/Makefile @@ -1,9 +1,9 @@ DEPS_SUBMODULES += lib/FreeRTOS-Kernel -include ../../make.mk +include ../../build_system/make/make.mk FREERTOS_SRC = lib/FreeRTOS-Kernel -FREERTOS_PORTABLE_PATH= $(FREERTOS_SRC)/portable/$(if $(USE_IAR),IAR,GCC) +FREERTOS_PORTABLE_PATH= $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC) INC += \ src \ @@ -44,4 +44,4 @@ CFLAGS_GCC += -Wno-error=cast-qual # FreeRTOS (lto + Os) linker issue LDFLAGS_GCC += -Wl,--undefined=vTaskSwitchContext -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h index 69d638288..6cc7a6577 100644 --- a/examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h +++ b/examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h @@ -96,6 +96,7 @@ #define configUSE_TICK_HOOK 0 #define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning #define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 /* Run time and task stats gathering related definitions. */ #define configGENERATE_RUN_TIME_STATS 0 @@ -130,23 +131,6 @@ #define INCLUDE_xEventGroupSetBitFromISR 0 #define INCLUDE_xTimerPendFunctionCall 0 -/* Define to trap errors during development. */ -// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 -#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) - #define configASSERT(_exp) \ - do {\ - if ( !(_exp) ) { \ - volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ - if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ - taskDISABLE_INTERRUPTS(); \ - __asm("BKPT #0\n"); \ - }\ - }\ - } while(0) -#else - #define configASSERT( x ) -#endif - #ifdef __RX__ /* Renesas RX series */ #define vSoftwareInterruptISR INT_Excep_ICU_SWINT diff --git a/examples/device/hid_composite_freertos/src/freertos_hook.c b/examples/device/hid_composite_freertos/src/freertos_hook.c index ab885947c..4920e3fae 100644 --- a/examples/device/hid_composite_freertos/src/freertos_hook.c +++ b/examples/device/hid_composite_freertos/src/freertos_hook.c @@ -99,9 +99,10 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, Stack void vApplicationSetupTimerInterrupt(void) { /* Enable CMT0 */ + unsigned short oldPRCR = SYSTEM.PRCR.WORD; SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1); MSTP(CMT0) = 0; - SYSTEM.PRCR.WORD = (0xA5u<<8); + SYSTEM.PRCR.WORD = (0xA5u<<8) | oldPRCR; CMT0.CMCNT = 0; CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128); diff --git a/examples/device/hid_composite_freertos/src/main.c b/examples/device/hid_composite_freertos/src/main.c index ff2cb635e..2bd545bc2 100644 --- a/examples/device/hid_composite_freertos/src/main.c +++ b/examples/device/hid_composite_freertos/src/main.c @@ -31,7 +31,7 @@ #include "tusb.h" #include "usb_descriptors.h" -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF // ESP-IDF need "freertos/" prefix in include path. // CFG_TUSB_OS_INC_PATH should be defined accordingly. #include "freertos/FreeRTOS.h" @@ -113,14 +113,14 @@ int main(void) xTimerStart(blinky_tm, 0); // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 -#if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if !TUP_MCU_ESPRESSIF vTaskStartScheduler(); #endif return 0; } -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF void app_main(void) { main(); diff --git a/examples/device/hid_composite_freertos/src/tusb_config.h b/examples/device/hid_composite_freertos/src/tusb_config.h index 3ba9bf311..0689e0f23 100644 --- a/examples/device/hid_composite_freertos/src/tusb_config.h +++ b/examples/device/hid_composite_freertos/src/tusb_config.h @@ -59,7 +59,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/device/hid_generic_inout/Makefile b/examples/device/hid_generic_inout/Makefile index da088ea6b..1b4d398cf 100644 --- a/examples/device/hid_generic_inout/Makefile +++ b/examples/device/hid_generic_inout/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -8,4 +8,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/hid_multiple_interface/Makefile b/examples/device/hid_multiple_interface/Makefile index da088ea6b..1b4d398cf 100644 --- a/examples/device/hid_multiple_interface/Makefile +++ b/examples/device/hid_multiple_interface/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -8,4 +8,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/midi_test/Makefile b/examples/device/midi_test/Makefile index 2a3d854fb..7fa475da5 100644 --- a/examples/device/midi_test/Makefile +++ b/examples/device/midi_test/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -8,4 +8,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/msc_dual_lun/Makefile b/examples/device/msc_dual_lun/Makefile index 2a3d854fb..7fa475da5 100644 --- a/examples/device/msc_dual_lun/Makefile +++ b/examples/device/msc_dual_lun/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -8,4 +8,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/msc_dual_lun/skip.txt b/examples/device/msc_dual_lun/skip.txt index 47e561cf0..a9e3a99b1 100644 --- a/examples/device/msc_dual_lun/skip.txt +++ b/examples/device/msc_dual_lun/skip.txt @@ -1,2 +1,3 @@ mcu:SAMD11 mcu:MKL25ZXX +family:espressif diff --git a/examples/device/msc_dual_lun/src/main.c b/examples/device/msc_dual_lun/src/main.c index de402d3da..aabd0bf8a 100644 --- a/examples/device/msc_dual_lun/src/main.c +++ b/examples/device/msc_dual_lun/src/main.c @@ -39,7 +39,7 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -50,8 +50,7 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; void led_blinking_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port @@ -61,8 +60,7 @@ int main(void) board_init_after_tusb(); } - while (1) - { + while (1) { tud_task(); // tinyusb device task led_blinking_task(); } @@ -73,42 +71,37 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ +void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void) { static uint32_t start_ms = 0; static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/net_lwip_webserver/CMakeLists.txt b/examples/device/net_lwip_webserver/CMakeLists.txt index a16b8bd71..c39fd32c5 100644 --- a/examples/device/net_lwip_webserver/CMakeLists.txt +++ b/examples/device/net_lwip_webserver/CMakeLists.txt @@ -74,6 +74,7 @@ target_sources(${PROJECT} PUBLIC ${LWIP}/src/netif/slipif.c ${LWIP}/src/apps/http/httpd.c ${LWIP}/src/apps/http/fs.c + ${LWIP}/src/apps/lwiperf/lwiperf.c ) # due to warnings from other net source, we need to prevent error from some of the warnings options diff --git a/examples/device/net_lwip_webserver/Makefile b/examples/device/net_lwip_webserver/Makefile index 90b429d00..141532466 100644 --- a/examples/device/net_lwip_webserver/Makefile +++ b/examples/device/net_lwip_webserver/Makefile @@ -1,6 +1,6 @@ DEPS_SUBMODULES += lib/lwip -include ../../make.mk +include ../../build_system/make/make.mk # suppress warning caused by lwip CFLAGS_GCC += \ @@ -63,8 +63,9 @@ SRC_C += \ lib/lwip/src/netif/slipif.c \ lib/lwip/src/apps/http/httpd.c \ lib/lwip/src/apps/http/fs.c \ + lib/lwip/src/apps/lwiperf/lwiperf.c \ lib/networking/dhserver.c \ lib/networking/dnserver.c \ lib/networking/rndis_reports.c -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/net_lwip_webserver/skip.txt b/examples/device/net_lwip_webserver/skip.txt index e3a726a2b..bb3ff7885 100644 --- a/examples/device/net_lwip_webserver/skip.txt +++ b/examples/device/net_lwip_webserver/skip.txt @@ -1,11 +1,14 @@ mcu:LPC11UXX mcu:LPC13XX +mcu:LPC15XX mcu:MSP430x5xx mcu:NUC121 mcu:SAMD11 mcu:STM32L0 +mcu:STM32F0 mcu:KINETIS_KL family:broadcom_64bit family:broadcom_32bit board:curiosity_nano board:frdm_kl25z +family:espressif diff --git a/examples/device/net_lwip_webserver/src/lwipopts.h b/examples/device/net_lwip_webserver/src/lwipopts.h index 336c9243d..41e8f0d67 100644 --- a/examples/device/net_lwip_webserver/src/lwipopts.h +++ b/examples/device/net_lwip_webserver/src/lwipopts.h @@ -48,8 +48,8 @@ #define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67)) #define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/) -#define TCP_SND_BUF (2 * TCP_MSS) -#define TCP_WND (TCP_MSS) +#define TCP_SND_BUF (4 * TCP_MSS) +#define TCP_WND (4 * TCP_MSS) #define ETHARP_SUPPORT_STATIC_ENTRIES 1 @@ -59,7 +59,7 @@ #define LWIP_SINGLE_NETIF 1 -#define PBUF_POOL_SIZE 2 +#define PBUF_POOL_SIZE 4 #define HTTPD_USE_CUSTOM_FSDATA 0 diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index 7d98aacbc..791e09b4f 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -48,12 +48,17 @@ try changing the first byte of tud_network_mac_address[] below from 0x02 to 0x00 #include "dhserver.h" #include "dnserver.h" +#include "httpd.h" +#include "lwip/ethip6.h" #include "lwip/init.h" #include "lwip/timeouts.h" -#include "lwip/ethip6.h" -#include "httpd.h" -#define INIT_IP4(a,b,c,d) { PP_HTONL(LWIP_MAKEU32(a,b,c,d)) } +#ifdef INCLUDE_IPERF + #include "lwip/apps/lwiperf.h" +#endif + +#define INIT_IP4(a, b, c, d) \ + { PP_HTONL(LWIP_MAKEU32(a, b, c, d)) } /* lwip context */ static struct netif netif_data; @@ -64,44 +69,40 @@ static struct pbuf *received_frame; /* this is used by this code, ./class/net/net_driver.c, and usb_descriptors.c */ /* ideally speaking, this should be generated from the hardware's unique ID (if available) */ /* it is suggested that the first byte is 0x02 to indicate a link-local address */ -uint8_t tud_network_mac_address[6] = {0x02,0x02,0x84,0x6A,0x96,0x00}; +uint8_t tud_network_mac_address[6] = {0x02, 0x02, 0x84, 0x6A, 0x96, 0x00}; /* network parameters of this MCU */ -static const ip4_addr_t ipaddr = INIT_IP4(192, 168, 7, 1); +static const ip4_addr_t ipaddr = INIT_IP4(192, 168, 7, 1); static const ip4_addr_t netmask = INIT_IP4(255, 255, 255, 0); static const ip4_addr_t gateway = INIT_IP4(0, 0, 0, 0); /* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ -static dhcp_entry_t entries[] = -{ - /* mac ip address lease time */ - { {0}, INIT_IP4(192, 168, 7, 2), 24 * 60 * 60 }, - { {0}, INIT_IP4(192, 168, 7, 3), 24 * 60 * 60 }, - { {0}, INIT_IP4(192, 168, 7, 4), 24 * 60 * 60 }, +static dhcp_entry_t entries[] = { + /* mac ip address lease time */ + {{0}, INIT_IP4(192, 168, 7, 2), 24 * 60 * 60}, + {{0}, INIT_IP4(192, 168, 7, 3), 24 * 60 * 60}, + {{0}, INIT_IP4(192, 168, 7, 4), 24 * 60 * 60}, }; -static const dhcp_config_t dhcp_config = -{ - .router = INIT_IP4(0, 0, 0, 0), /* router address (if any) */ - .port = 67, /* listen port */ - .dns = INIT_IP4(192, 168, 7, 1), /* dns server (if any) */ - "usb", /* dns suffix */ - TU_ARRAY_SIZE(entries), /* num entry */ - entries /* entries */ +static const dhcp_config_t dhcp_config = { + .router = INIT_IP4(0, 0, 0, 0), /* router address (if any) */ + .port = 67, /* listen port */ + .dns = INIT_IP4(192, 168, 7, 1), /* dns server (if any) */ + "usb", /* dns suffix */ + TU_ARRAY_SIZE(entries), /* num entry */ + entries /* entries */ }; -static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) -{ - (void)netif; - for (;;) - { +static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) { + (void) netif; + + for (;;) { /* if TinyUSB isn't ready, we must signal back to lwip that there is nothing we can do */ if (!tud_ready()) return ERR_USE; /* if the network driver can accept another packet, we make it happen */ - if (tud_network_can_xmit(p->tot_len)) - { + if (tud_network_can_xmit(p->tot_len)) { tud_network_xmit(p, 0 /* unused for this example */); return ERR_OK; } @@ -111,20 +112,17 @@ static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) } } -static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) -{ +static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) { return etharp_output(netif, p, addr); } #if LWIP_IPV6 -static err_t ip6_output_fn(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) -{ +static err_t ip6_output_fn(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) { return ethip6_output(netif, p, addr); } #endif -static err_t netif_init_cb(struct netif *netif) -{ +static err_t netif_init_cb(struct netif *netif) { LWIP_ASSERT("netif != NULL", (netif != NULL)); netif->mtu = CFG_TUD_NET_MTU; netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; @@ -139,8 +137,7 @@ static err_t netif_init_cb(struct netif *netif) return ERR_OK; } -static void init_lwip(void) -{ +static void init_lwip(void) { struct netif *netif = &netif_data; lwip_init(); @@ -158,28 +155,23 @@ static void init_lwip(void) } /* handle any DNS requests from dns-server */ -bool dns_query_proc(const char *name, ip4_addr_t *addr) -{ - if (0 == strcmp(name, "tiny.usb")) - { +bool dns_query_proc(const char *name, ip4_addr_t *addr) { + if (0 == strcmp(name, "tiny.usb")) { *addr = ipaddr; return true; } return false; } -bool tud_network_recv_cb(const uint8_t *src, uint16_t size) -{ +bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { /* this shouldn't happen, but if we get another packet before parsing the previous, we must signal our inability to accept it */ if (received_frame) return false; - if (size) - { + if (size) { struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); - if (p) - { + if (p) { /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ memcpy(p->payload, src, size); @@ -191,20 +183,17 @@ bool tud_network_recv_cb(const uint8_t *src, uint16_t size) return true; } -uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) -{ - struct pbuf *p = (struct pbuf *)ref; +uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) { + struct pbuf *p = (struct pbuf *) ref; - (void)arg; /* unused for this example */ + (void) arg; /* unused for this example */ return pbuf_copy_partial(p, dst, p->tot_len, 0); } -static void service_traffic(void) -{ +static void service_traffic(void) { /* handle any packet received by tud_network_recv_cb() */ - if (received_frame) - { + if (received_frame) { ethernet_input(received_frame, &netif_data); pbuf_free(received_frame); received_frame = NULL; @@ -214,18 +203,15 @@ static void service_traffic(void) sys_check_timeouts(); } -void tud_network_init_cb(void) -{ +void tud_network_init_cb(void) { /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ - if (received_frame) - { + if (received_frame) { pbuf_free(received_frame); received_frame = NULL; } } -int main(void) -{ +int main(void) { /* initialize TinyUSB */ board_init(); @@ -243,8 +229,12 @@ int main(void) while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK); httpd_init(); - while (1) - { +#ifdef INCLUDE_IPERF + // test with: iperf -c 192.168.7.1 -e -i 1 -M 5000 -l 8192 -r + lwiperf_start_tcp_server_default(NULL, NULL); +#endif + + while (1) { tud_task(); service_traffic(); } @@ -253,17 +243,14 @@ int main(void) } /* lwip has provision for using a mutex, when applicable */ -sys_prot_t sys_arch_protect(void) -{ +sys_prot_t sys_arch_protect(void) { return 0; } -void sys_arch_unprotect(sys_prot_t pval) -{ - (void)pval; +void sys_arch_unprotect(sys_prot_t pval) { + (void) pval; } /* lwip needs a millisecond time source, and the TinyUSB board support code has one available */ -uint32_t sys_now(void) -{ +uint32_t sys_now(void) { return board_millis(); } diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index fe72ecdfe..d3e094517 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -27,21 +27,23 @@ #define _TUSB_CONFIG_H_ #ifdef __cplusplus - extern "C" { +extern "C" { #endif +#include "lwipopts.h" + //--------------------------------------------------------------------+ // Board Specific Configuration //--------------------------------------------------------------------+ // RHPort number used for device can be defined by board.mk, default to port 0 #ifndef BOARD_TUD_RHPORT -#define BOARD_TUD_RHPORT 0 + #define BOARD_TUD_RHPORT 0 #endif // RHPort max operational speed can defined by board.mk #ifndef BOARD_TUD_MAX_SPEED -#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED + #define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED #endif //-------------------------------------------------------------------- @@ -50,22 +52,22 @@ // defined by compiler flags for flexibility #ifndef CFG_TUSB_MCU -#error CFG_TUSB_MCU must be defined + #error CFG_TUSB_MCU must be defined #endif #ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_NONE + #define CFG_TUSB_OS OPT_OS_NONE #endif #ifndef CFG_TUSB_DEBUG -#define CFG_TUSB_DEBUG 0 + #define CFG_TUSB_DEBUG 0 #endif // Enable Device stack -#define CFG_TUD_ENABLED 1 +#define CFG_TUD_ENABLED 1 // Default is max speed that hardware controller could support with on-chip PHY -#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED +#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. * Tinyusb use follows macros to declare transferring memory so that they can be put @@ -75,11 +77,45 @@ * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) */ #ifndef CFG_TUSB_MEM_SECTION -#define CFG_TUSB_MEM_SECTION + #define CFG_TUSB_MEM_SECTION #endif #ifndef CFG_TUSB_MEM_ALIGN -#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) + #define CFG_TUSB_MEM_ALIGN __attribute__((aligned(4))) +#endif + +// Use different configurations to test all net devices (also due to resource limitations) +#if TU_CHECK_MCU(OPT_MCU_LPC15XX, OPT_MCU_LPC40XX, OPT_MCU_LPC51UXX, OPT_MCU_LPC54) + #define USE_ECM 1 +#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAML21, OPT_MCU_SAML22) + #define USE_ECM 1 +#elif TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32F1) + #define USE_ECM 1 +#else + #define USE_ECM 0 + #define INCLUDE_IPERF +#endif + +//-------------------------------------------------------------------- +// NCM CLASS CONFIGURATION, SEE "ncm.h" FOR PERFORMANCE TUNING +//-------------------------------------------------------------------- + +// Must be >> MTU +// Can be set to 2048 without impact +#define CFG_TUD_NCM_IN_NTB_MAX_SIZE (2 * TCP_MSS + 100) + +// Must be >> MTU +// Can be set to smaller values if wNtbOutMaxDatagrams==1 +#define CFG_TUD_NCM_OUT_NTB_MAX_SIZE (2 * TCP_MSS + 100) + +// Number of NCM transfer blocks for reception side +#ifndef CFG_TUD_NCM_OUT_NTB_N + #define CFG_TUD_NCM_OUT_NTB_N 1 +#endif + +// Number of NCM transfer blocks for transmission side +#ifndef CFG_TUD_NCM_IN_NTB_N + #define CFG_TUD_NCM_IN_NTB_N 1 #endif //-------------------------------------------------------------------- @@ -87,18 +123,18 @@ //-------------------------------------------------------------------- #ifndef CFG_TUD_ENDPOINT0_SIZE -#define CFG_TUD_ENDPOINT0_SIZE 64 + #define CFG_TUD_ENDPOINT0_SIZE 64 #endif //------------- CLASS -------------// // Network class has 2 drivers: ECM/RNDIS and NCM. // Only one of the drivers can be enabled -#define CFG_TUD_ECM_RNDIS 1 -#define CFG_TUD_NCM (1-CFG_TUD_ECM_RNDIS) +#define CFG_TUD_ECM_RNDIS USE_ECM +#define CFG_TUD_NCM (1 - CFG_TUD_ECM_RNDIS) #ifdef __cplusplus - } +} #endif #endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/uac2_headset/Makefile b/examples/device/uac2_headset/Makefile index 2a3d854fb..7fa475da5 100644 --- a/examples/device/uac2_headset/Makefile +++ b/examples/device/uac2_headset/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -8,4 +8,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/uac2_headset/skip.txt b/examples/device/uac2_headset/skip.txt index 70d8e8838..a2a76af0e 100644 --- a/examples/device/uac2_headset/skip.txt +++ b/examples/device/uac2_headset/skip.txt @@ -5,3 +5,4 @@ mcu:SAMD11 mcu:SAME5X mcu:SAMG board:stm32l052dap52 +family:espressif diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index 0ab72b2f3..0ea6e7025 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -35,11 +35,7 @@ //--------------------------------------------------------------------+ // List of supported sample rates -#if defined(__RX__) - const uint32_t sample_rates[] = {44100, 48000}; -#else - const uint32_t sample_rates[] = {44100, 48000, 88200, 96000}; -#endif +const uint32_t sample_rates[] = {44100, 48000}; uint32_t current_sample_rate = 44100; @@ -96,6 +92,7 @@ uint8_t current_resolution; void led_blinking_task(void); void audio_task(void); +void audio_control_task(void); /*------------- MAIN -------------*/ int main(void) @@ -115,6 +112,7 @@ int main(void) { tud_task(); // TinyUSB device task audio_task(); + audio_control_task(); led_blinking_task(); } } @@ -159,7 +157,7 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t { if (request->bRequest == AUDIO_CS_REQ_CUR) { - TU_LOG1("Clock get current freq %lu\r\n", current_sample_rate); + TU_LOG1("Clock get current freq %" PRIu32 "\r\n", current_sample_rate); audio_control_cur_4_t curf = { (int32_t) tu_htole32(current_sample_rate) }; return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &curf, sizeof(curf)); @@ -208,7 +206,7 @@ static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t current_sample_rate = (uint32_t) ((audio_control_cur_4_t const *)buf)->bCur; - TU_LOG1("Clock set current freq: %ld\r\n", current_sample_rate); + TU_LOG1("Clock set current freq: %" PRIu32 "\r\n", current_sample_rate); return true; } @@ -428,6 +426,45 @@ void audio_task(void) } } +void audio_control_task(void) +{ + // Press on-board button to control volume + // Open host volume control, volume should switch between 10% and 100% + + // Poll every 50ms + const uint32_t interval_ms = 50; + static uint32_t start_ms = 0; + static uint32_t btn_prev = 0; + + if ( board_millis() - start_ms < interval_ms) return; // not enough time + start_ms += interval_ms; + + uint32_t btn = board_button_read(); + + if (!btn_prev && btn) + { + // Adjust volume between 0dB (100%) and -30dB (10%) + for (int i = 0; i < CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1; i++) + { + volume[i] = volume[i] == 0 ? -VOLUME_CTRL_30_DB : 0; + } + + // 6.1 Interrupt Data Message + const audio_interrupt_data_t data = { + .bInfo = 0, // Class-specific interrupt, originated from an interface + .bAttribute = AUDIO_CS_REQ_CUR, // Caused by current settings + .wValue_cn_or_mcn = 0, // CH0: master volume + .wValue_cs = AUDIO_FU_CTRL_VOLUME, // Volume change + .wIndex_ep_or_int = 0, // From the interface itself + .wIndex_entity_id = UAC2_ENTITY_SPK_FEATURE_UNIT, // From feature unit + }; + + tud_audio_int_write(&data); + } + + btn_prev = btn; +} + //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 1a3e23e95..328e35f52 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -105,17 +105,18 @@ extern "C" { // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- +// Allow volume controlled by on-baord button +#define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP 1 + #define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN // How many formats are used, need to adjust USB descriptor if changed #define CFG_TUD_AUDIO_FUNC_1_N_FORMATS 2 // Audio format type I specifications -#if defined(__RX__) -#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 48000 // 16bit/48kHz is the best quality for Renesas RX -#else -#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 96000 // 24bit/96kHz is the best quality for full-speed, high-speed is needed beyond this -#endif +/* 24bit/48kHz is the best quality for headset or 24bit/96kHz for 2ch speaker, + high-speed is needed beyond this */ +#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 48000 #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX 2 @@ -151,11 +152,11 @@ extern "C" { // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 -#define CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) -#define CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) +#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) +#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT)*2 -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT) // Maximum EP IN size for all AS alternate settings used +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_OUT)*2 +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_OUT) // Maximum EP IN size for all AS alternate settings used // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) #define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 2 diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index 6d1e6a23f..ff4dc2acc 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -82,27 +82,32 @@ uint8_t const * tud_descriptor_device_cb(void) // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... #define EPNUM_AUDIO_IN 0x03 #define EPNUM_AUDIO_OUT 0x03 + #define EPNUM_AUDIO_INT 0x01 #elif CFG_TUSB_MCU == OPT_MCU_NRF5X // ISO endpoints for NRF5x are fixed to 0x08 (0x88) #define EPNUM_AUDIO_IN 0x08 #define EPNUM_AUDIO_OUT 0x08 + #define EPNUM_AUDIO_INT 0x01 #elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_AUDIO_IN 0x01 #define EPNUM_AUDIO_OUT 0x02 + #define EPNUM_AUDIO_INT 0x03 #elif CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X // FT9XX doesn't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_AUDIO_IN 0x01 #define EPNUM_AUDIO_OUT 0x02 + #define EPNUM_AUDIO_INT 0x03 #else #define EPNUM_AUDIO_IN 0x01 #define EPNUM_AUDIO_OUT 0x01 + #define EPNUM_AUDIO_INT 0x02 #endif uint8_t const desc_configuration[] = @@ -111,7 +116,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80) + TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80, EPNUM_AUDIO_INT | 0x80) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/uac2_headset/src/usb_descriptors.h b/examples/device/uac2_headset/src/usb_descriptors.h index d7e170162..da0da83e8 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.h +++ b/examples/device/uac2_headset/src/usb_descriptors.h @@ -55,6 +55,7 @@ enum + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_STD_AC_INT_EP_LEN\ /* Interface 1, Alternate 0 */\ + TUD_AUDIO_DESC_STD_AS_INT_LEN\ /* Interface 1, Alternate 1 */\ @@ -84,11 +85,11 @@ enum + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) -#define TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(_stridx, _epout, _epin) \ +#define TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(_stridx, _epout, _epin, _epint) \ /* Standard Interface Association Descriptor (IAD) */\ TUD_AUDIO_DESC_IAD(/*_firstitf*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ ITF_NUM_TOTAL, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_nEPs*/ 0x01, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_HEADSET, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ /* Clock Source Descriptor(4.7.2.1) */\ @@ -103,6 +104,8 @@ enum TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ /* Output Terminal Descriptor(4.7.2.5) */\ TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Standard AC Interrupt Endpoint Descriptor(4.8.2.1) */\ + TUD_AUDIO_DESC_STD_AC_INT_EP(/*_ep*/ _epint, /*_interval*/ 0x01), \ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x05),\ @@ -114,7 +117,7 @@ enum /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ADAPTIVE | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ /* Interface 1, Alternate 2 - alternate interface for data streaming */\ @@ -124,7 +127,7 @@ enum /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ADAPTIVE | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ /* Standard AS Interface Descriptor(4.9.1) */\ @@ -138,7 +141,7 @@ enum /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_TX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ /* Interface 2, Alternate 2 - alternate interface for data streaming */\ @@ -148,7 +151,7 @@ enum /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) diff --git a/examples/device/usbtmc/Makefile b/examples/device/usbtmc/Makefile index da088ea6b..1b4d398cf 100644 --- a/examples/device/usbtmc/Makefile +++ b/examples/device/usbtmc/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -8,4 +8,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/usbtmc/skip.txt b/examples/device/usbtmc/skip.txt index a43106cf0..ccff857ac 100644 --- a/examples/device/usbtmc/skip.txt +++ b/examples/device/usbtmc/skip.txt @@ -1 +1,2 @@ mcu:BCM2835 +family:espressif diff --git a/examples/device/video_capture/Makefile b/examples/device/video_capture/Makefile index 90d174c32..d698a848d 100644 --- a/examples/device/video_capture/Makefile +++ b/examples/device/video_capture/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk ifeq ($(DISABLE_MJPEG),1) CFLAGS += -DCFG_EXAMPLE_VIDEO_DISABLE_MJPEG @@ -15,4 +15,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk diff --git a/examples/device/video_capture/skip.txt b/examples/device/video_capture/skip.txt index 5898664a2..db64cc639 100644 --- a/examples/device/video_capture/skip.txt +++ b/examples/device/video_capture/skip.txt @@ -1,3 +1,4 @@ mcu:MSP430x5xx mcu:NUC121 mcu:SAMD11 +family:espressif diff --git a/examples/device/video_capture/src/CMakeLists.txt b/examples/device/video_capture/src/CMakeLists.txt new file mode 100644 index 000000000..cef2b46ee --- /dev/null +++ b/examples/device/video_capture/src/CMakeLists.txt @@ -0,0 +1,4 @@ +# This file is for ESP-IDF only +idf_component_register(SRCS "main.c" "usb_descriptors.c" + INCLUDE_DIRS "." + REQUIRES boards tinyusb_src) diff --git a/examples/device/video_capture/src/images.h b/examples/device/video_capture/src/images.h index 0398428b3..ac372cb16 100644 --- a/examples/device/video_capture/src/images.h +++ b/examples/device/video_capture/src/images.h @@ -1,4 +1,5 @@ -#if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPG) +#if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) +// uncopmressed frame static const unsigned char frame_buffer[128 * (96 + 1) * 2] = { /* 0 */ 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, @@ -1650,8 +1651,10 @@ static const unsigned char frame_buffer[128 * (96 + 1) * 2] = { 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, }; + #else +// mpeg compressed data (not CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) #define color_bar_0_jpg_len 511 #define color_bar_1_jpg_len 512 #define color_bar_2_jpg_len 511 diff --git a/examples/device/video_capture/src/main.c b/examples/device/video_capture/src/main.c index c653761c1..ddb51e03a 100644 --- a/examples/device/video_capture/src/main.c +++ b/examples/device/video_capture/src/main.c @@ -40,7 +40,7 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -48,14 +48,25 @@ enum { static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; -void led_blinking_task(void); -void video_task(void); +void led_blinking_task(void* param); +void usb_device_task(void *param); +void video_task(void* param); -/*------------- MAIN -------------*/ -int main(void) -{ +#if CFG_TUSB_OS == OPT_OS_FREERTOS +void freertos_init_task(void); +#endif + + +//--------------------------------------------------------------------+ +// Main +//--------------------------------------------------------------------+ +int main(void) { board_init(); + // If using FreeRTOS: create blinky, tinyusb device, video task +#if CFG_TUSB_OS == OPT_OS_FREERTOS + freertos_init_task(); +#else // init device stack on configured roothub port tud_init(BOARD_TUD_RHPORT); @@ -63,13 +74,12 @@ int main(void) board_init_after_tusb(); } - while (1) - { + while (1) { tud_task(); // tinyusb device task - led_blinking_task(); - - video_task(); + led_blinking_task(NULL); + video_task(NULL); } +#endif } //--------------------------------------------------------------------+ @@ -77,33 +87,28 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ +void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } - //--------------------------------------------------------------------+ // USB Video //--------------------------------------------------------------------+ @@ -111,11 +116,12 @@ static unsigned frame_num = 0; static unsigned tx_busy = 0; static unsigned interval_ms = 1000 / FRAME_RATE; -/* YUY2 frame buffer */ #ifdef CFG_EXAMPLE_VIDEO_READONLY +// For mcus that does not have enough SRAM for frame buffer, we use fixed frame data. +// To further reduce the size, we use MJPEG format instead of YUY2. #include "images.h" -# if !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPG) +#if !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) static struct { uint32_t size; uint8_t const *buffer; @@ -129,29 +135,30 @@ static struct { {color_bar_6_jpg_len, color_bar_6_jpg}, {color_bar_7_jpg_len, color_bar_7_jpg}, }; -# endif +#endif #else + +// YUY2 frame buffer static uint8_t frame_buffer[FRAME_WIDTH * FRAME_HEIGHT * 16 / 8]; -static void fill_color_bar(uint8_t *buffer, unsigned start_position) -{ - /* EBU color bars - * See also https://stackoverflow.com/questions/6939422 */ + +static void fill_color_bar(uint8_t* buffer, unsigned start_position) { + /* EBU color bars: https://stackoverflow.com/questions/6939422 */ static uint8_t const bar_color[8][4] = { - /* Y, U, Y, V */ - { 235, 128, 235, 128}, /* 100% White */ - { 219, 16, 219, 138}, /* Yellow */ - { 188, 154, 188, 16}, /* Cyan */ - { 173, 42, 173, 26}, /* Green */ - { 78, 214, 78, 230}, /* Magenta */ - { 63, 102, 63, 240}, /* Red */ - { 32, 240, 32, 118}, /* Blue */ - { 16, 128, 16, 128}, /* Black */ + /* Y, U, Y, V */ + { 235, 128, 235, 128}, /* 100% White */ + { 219, 16, 219, 138}, /* Yellow */ + { 188, 154, 188, 16}, /* Cyan */ + { 173, 42, 173, 26}, /* Green */ + { 78, 214, 78, 230}, /* Magenta */ + { 63, 102, 63, 240}, /* Red */ + { 32, 240, 32, 118}, /* Blue */ + { 16, 128, 16, 128}, /* Black */ }; - uint8_t *p; + uint8_t* p; /* Generate the 1st line */ - uint8_t *end = &buffer[FRAME_WIDTH * 2]; + uint8_t* end = &buffer[FRAME_WIDTH * 2]; unsigned idx = (FRAME_WIDTH / 2 - 1) - (start_position % (FRAME_WIDTH / 2)); p = &buffer[idx * 4]; for (unsigned i = 0; i < 8; ++i) { @@ -163,6 +170,7 @@ static void fill_color_bar(uint8_t *buffer, unsigned start_position) } } } + /* Duplicate the 1st line to the others */ p = &buffer[FRAME_WIDTH * 2]; for (unsigned i = 1; i < FRAME_HEIGHT; ++i) { @@ -170,32 +178,33 @@ static void fill_color_bar(uint8_t *buffer, unsigned start_position) p += FRAME_WIDTH * 2; } } + #endif -void video_task(void) -{ +void video_send_frame(void) { static unsigned start_ms = 0; static unsigned already_sent = 0; if (!tud_video_n_streaming(0, 0)) { - already_sent = 0; - frame_num = 0; + already_sent = 0; + frame_num = 0; return; } if (!already_sent) { already_sent = 1; + tx_busy = 1; start_ms = board_millis(); #ifdef CFG_EXAMPLE_VIDEO_READONLY -# if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPG) + #if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t)&frame_buffer[(frame_num % (FRAME_WIDTH / 2)) * 4], FRAME_WIDTH * FRAME_HEIGHT * 16/8); -# else + #else tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t)frames[frame_num % 8].buffer, frames[frame_num % 8].size); -# endif + #endif #else fill_color_bar(frame_buffer, frame_num); - tud_video_n_frame_xfer(0, 0, (void*)frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16/8); + tud_video_n_frame_xfer(0, 0, (void*) frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); #endif } @@ -203,49 +212,140 @@ void video_task(void) if (cur - start_ms < interval_ms) return; // not enough time if (tx_busy) return; start_ms += interval_ms; + tx_busy = 1; #ifdef CFG_EXAMPLE_VIDEO_READONLY -# if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPG) + #if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t)&frame_buffer[(frame_num % (FRAME_WIDTH / 2)) * 4], FRAME_WIDTH * FRAME_HEIGHT * 16/8); -# else + #else tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t)frames[frame_num % 8].buffer, frames[frame_num % 8].size); -# endif + #endif #else fill_color_bar(frame_buffer, frame_num); - tud_video_n_frame_xfer(0, 0, (void*)frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16/8); + tud_video_n_frame_xfer(0, 0, (void*) frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); #endif } -void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) -{ - (void)ctl_idx; (void)stm_idx; + +void video_task(void* param) { + (void) param; + + while(1) { + video_send_frame(); + + #if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(interval_ms / portTICK_PERIOD_MS); + #else + return; + #endif + } +} + +void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { + (void) ctl_idx; + (void) stm_idx; tx_busy = 0; /* flip buffer */ ++frame_num; } int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, - video_probe_and_commit_control_t const *parameters) -{ - (void)ctl_idx; (void)stm_idx; + video_probe_and_commit_control_t const* parameters) { + (void) ctl_idx; + (void) stm_idx; /* convert unit to ms from 100 ns */ interval_ms = parameters->dwFrameInterval / 10000; return VIDEO_ERROR_NONE; } //--------------------------------------------------------------------+ -// BLINKING TASK +// Blinking Task //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void* param) { + (void) param; static uint32_t start_ms = 0; static bool led_state = false; - // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time - start_ms += blink_interval_ms; + while (1) { + #if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + #else + if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + #endif - board_led_write(led_state); - led_state = 1 - led_state; // toggle + start_ms += blink_interval_ms; + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } } + +//--------------------------------------------------------------------+ +// FreeRTOS +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS + +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define VIDEO_STACK_SIZE (configMINIMAL_STACK_SIZE*4) + +#if TUP_MCU_ESPRESSIF + #define USBD_STACK_SIZE 4096 + int main(void); + void app_main(void) { + main(); + } +#else + // Increase stack size when debug log is enabled + #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) +#endif + +// static task +#if configSUPPORT_STATIC_ALLOCATION +StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StaticTask_t blinky_taskdef; + +StackType_t usb_device_stack[USBD_STACK_SIZE]; +StaticTask_t usb_device_taskdef; + +StackType_t video_stack[VIDEO_STACK_SIZE]; +StaticTask_t video_taskdef; +#endif + +// USB Device Driver task +// This top level thread process all usb events and invoke callbacks +void usb_device_task(void *param) { + (void) param; + + // init device stack on configured roothub port + // This should be called after scheduler/kernel is started. + // Otherwise, it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tud_init(BOARD_TUD_RHPORT); + + if (board_init_after_tusb) { + board_init_after_tusb(); + } + + // RTOS forever loop + while (1) { + // put this thread to waiting state until there is new events + tud_task(); + } +} + +void freertos_init_task(void) { + #if configSUPPORT_STATIC_ALLOCATION + xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); + xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); + xTaskCreateStatic(video_task, "cdc", VIDEO_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, video_stack, &video_taskdef); + #else + xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + xTaskCreate(video_task, "video", VIDEO_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL); + #endif + + // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 + #if !TUP_MCU_ESPRESSIF + vTaskStartScheduler(); + #endif +} +#endif diff --git a/examples/device/video_capture/src/tusb_config.h b/examples/device/video_capture/src/tusb_config.h index 274bf2b9c..21483a2da 100644 --- a/examples/device/video_capture/src/tusb_config.h +++ b/examples/device/video_capture/src/tusb_config.h @@ -57,6 +57,11 @@ #define CFG_TUSB_OS OPT_OS_NONE #endif +// Espressif IDF requires "freertos/" prefix in include path +#if TUP_MCU_ESPRESSIF +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + #ifndef CFG_TUSB_DEBUG #define CFG_TUSB_DEBUG 0 #endif @@ -97,11 +102,14 @@ // The number of video streaming interfaces #define CFG_TUD_VIDEO_STREAMING 1 -// video streaming endpoint size +// video streaming endpoint buffer size #define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE 256 // use bulk endpoint for streaming interface -#define CFG_TUD_VIDEO_STREAMING_BULK 0 +#define CFG_TUD_VIDEO_STREAMING_BULK 1 + +//#define CFG_EXAMPLE_VIDEO_READONLY +//#define CFG_EXAMPLE_VIDEO_DISABLE_MJPEG #ifdef __cplusplus } diff --git a/examples/device/video_capture/src/usb_descriptors.c b/examples/device/video_capture/src/usb_descriptors.c index 292d86cd9..5011bee18 100644 --- a/examples/device/video_capture/src/usb_descriptors.c +++ b/examples/device/video_capture/src/usb_descriptors.c @@ -37,14 +37,36 @@ #define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VIDEO, 5) | _PID_MAP(VENDOR, 6) ) +#define USB_VID 0xCafe +#define USB_BCD 0x0200 + +// String Descriptor Index +enum { + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, + STRID_UVC_CONTROL, + STRID_UVC_STREAMING, +}; + +// array of pointer to string descriptors +char const* string_desc_arr[] = { + (const char[]) {0x09, 0x04}, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + NULL, // 3: Serials will use unique ID if possible + "UVC Control", // 4: UVC Interface + "UVC Streaming", // 5: UVC Interface +}; + //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = -{ +tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, + .bcdUSB = USB_BCD, // Use Interface Association Descriptor (IAD) for Video // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) @@ -54,130 +76,378 @@ tusb_desc_device_t const desc_device = .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0xCafe, + .idVendor = USB_VID, .idProduct = USB_PID, .bcdDevice = 0x0100, - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, + .iManufacturer = STRID_MANUFACTURER, + .iProduct = STRID_PRODUCT, + .iSerialNumber = STRID_SERIAL, .bNumConfigurations = 0x01 }; // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) -{ - return (uint8_t const *) &desc_device; +uint8_t const* tud_descriptor_device_cb(void) { + return (uint8_t const*) &desc_device; } //--------------------------------------------------------------------+ // Configuration Descriptor //--------------------------------------------------------------------+ -#if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK -# define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_DESC_MJPEG_BULK_LEN) -# else -# define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_DESC_MJPEG_LEN) -# endif -#else -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK -# define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_DESC_UNCOMPR_BULK_LEN) -# else -# define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN) -# endif -#endif +/* Time stamp base clock. It is a deprecated parameter. */ +#define UVC_CLOCK_FREQUENCY 27000000 +/* video capture path */ +#define UVC_ENTITY_CAP_INPUT_TERMINAL 0x01 +#define UVC_ENTITY_CAP_OUTPUT_TERMINAL 0x02 + +enum { + ITF_NUM_VIDEO_CONTROL, + ITF_NUM_VIDEO_STREAMING, + ITF_NUM_TOTAL +}; + +// Select appropriate endpoint number #if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ... -#if 1 == CFG_TUD_VIDEO_STREAMING_BULK - #define EPNUM_VIDEO_IN 0x82 + #define EPNUM_VIDEO_IN (CFG_TUD_VIDEO_STREAMING_BULK ? 0x82 : 0x83) +#elif TU_CHECK_MCU(OPT_MCU_NRF5X) + // nRF5x ISO can only be endpoint 8 + #define EPNUM_VIDEO_IN (CFG_TUD_VIDEO_STREAMING_BULK ? 0x81 : 0x88) #else - #define EPNUM_VIDEO_IN 0x83 + #define EPNUM_VIDEO_IN 0x81 #endif -#elif TU_CHECK_MCU(OPT_MCU_NRF5X) - // nRF5x ISO can only be endpoint 8 - #define EPNUM_VIDEO_IN 0x88 +#if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) + #define USE_MJPEG 1 +#else + #define USE_MJPEG 0 +#endif + +#define USE_ISO_STREAMING (!CFG_TUD_VIDEO_STREAMING_BULK) + +typedef struct TU_ATTR_PACKED { + tusb_desc_interface_t itf; + tusb_desc_video_control_header_1itf_t header; + tusb_desc_video_control_camera_terminal_t camera_terminal; + tusb_desc_video_control_output_terminal_t output_terminal; +} uvc_control_desc_t; +/* Windows support YUY2 and NV12 + * https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/usb-video-class-driver-overview */ + +typedef struct TU_ATTR_PACKED { + tusb_desc_interface_t itf; + tusb_desc_video_streaming_input_header_1byte_t header; + +#if USE_MJPEG + tusb_desc_video_format_mjpeg_t format; + tusb_desc_video_frame_mjpeg_continuous_t frame; #else - #define EPNUM_VIDEO_IN 0x81 + tusb_desc_video_format_uncompressed_t format; + tusb_desc_video_frame_uncompressed_continuous_t frame; +#endif + + tusb_desc_video_streaming_color_matching_t color; +#if USE_ISO_STREAMING + // For ISO streaming, USB spec requires to alternate interface + tusb_desc_interface_t itf_alt; #endif -uint8_t const desc_fs_configuration[] = -{ - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 500), + tusb_desc_endpoint_t ep; +} uvc_streaming_desc_t; - // IAD for Video Control -#if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK - TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - 64) -# else - TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) -# endif +typedef struct TU_ATTR_PACKED { + tusb_desc_configuration_t config; + tusb_desc_interface_assoc_t iad; + uvc_control_desc_t video_control; + uvc_streaming_desc_t video_streaming; +} uvc_cfg_desc_t; + +const uvc_cfg_desc_t desc_fs_configuration = { + .config = { + .bLength = sizeof(tusb_desc_configuration_t), + .bDescriptorType = TUSB_DESC_CONFIGURATION, + + .wTotalLength = sizeof(uvc_cfg_desc_t), + .bNumInterfaces = ITF_NUM_TOTAL, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = TU_BIT(7), + .bMaxPower = 100 / 2 + }, + .iad = { + .bLength = sizeof(tusb_desc_interface_assoc_t), + .bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION, + + .bFirstInterface = ITF_NUM_VIDEO_CONTROL, + .bInterfaceCount = 2, + .bFunctionClass = TUSB_CLASS_VIDEO, + .bFunctionSubClass = VIDEO_SUBCLASS_INTERFACE_COLLECTION, + .bFunctionProtocol = VIDEO_ITF_PROTOCOL_UNDEFINED, + .iFunction = 0 + }, + + .video_control = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_CONTROL, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_CONTROL, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_CONTROL + }, + .header = { + .bLength = sizeof(tusb_desc_video_control_header_1itf_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_HEADER, + + .bcdUVC = VIDEO_BCD_1_50, + .wTotalLength = sizeof(uvc_control_desc_t) - sizeof(tusb_desc_interface_t), // CS VC descriptors only + .dwClockFrequency = UVC_CLOCK_FREQUENCY, + .bInCollection = 1, + .baInterfaceNr = { ITF_NUM_VIDEO_STREAMING } + }, + .camera_terminal = { + .bLength = sizeof(tusb_desc_video_control_camera_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .wTerminalType = VIDEO_ITT_CAMERA, + .bAssocTerminal = 0, + .iTerminal = 0, + .wObjectiveFocalLengthMin = 0, + .wObjectiveFocalLengthMax = 0, + .wOcularFocalLength = 0, + .bControlSize = 3, + .bmControls = { 0, 0, 0 } + }, + .output_terminal = { + .bLength = sizeof(tusb_desc_video_control_output_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .wTerminalType = VIDEO_TT_STREAMING, + .bAssocTerminal = 0, + .bSourceID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .iTerminal = 0 + } + }, + + .video_streaming = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING, + .bAlternateSetting = 0, + .bNumEndpoints = CFG_TUD_VIDEO_STREAMING_BULK, // bulk 1, iso 0 + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING + }, + .header = { + .bLength = sizeof(tusb_desc_video_streaming_input_header_1byte_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_INPUT_HEADER, + + .bNumFormats = 1, + .wTotalLength = sizeof(uvc_streaming_desc_t) - sizeof(tusb_desc_interface_t) + - sizeof(tusb_desc_endpoint_t) - (USE_ISO_STREAMING ? sizeof(tusb_desc_interface_t) : 0) , // CS VS descriptors only + .bEndpointAddress = EPNUM_VIDEO_IN, + .bmInfo = 0, + .bTerminalLink = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .bStillCaptureMethod = 0, + .bTriggerSupport = 0, + .bTriggerUsage = 0, + .bControlSize = 1, + .bmaControls = { 0 } + }, + .format = { +#if USE_MJPEG + .bLength = sizeof(tusb_desc_video_format_mjpeg_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_MJPEG, + .bFormatIndex = 1, // 1-based index + .bNumFrameDescriptors = 1, + .bmFlags = 0, +#else + .bLength = sizeof(tusb_desc_video_format_uncompressed_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, + .bFormatIndex = 1, // 1-based index + .bNumFrameDescriptors = 1, + .guidFormat = { TUD_VIDEO_GUID_YUY2 }, + .bBitsPerPixel = 16, +#endif + .bDefaultFrameIndex = 1, + .bAspectRatioX = 0, + .bAspectRatioY = 0, + .bmInterlaceFlags = 0, + .bCopyProtect = 0 + }, + .frame = { +#if USE_MJPEG + .bLength = sizeof(tusb_desc_video_frame_mjpeg_continuous_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_MJPEG, #else -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK - TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR_BULK(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - 64) -# else - TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) -# endif + .bLength = sizeof(tusb_desc_video_frame_uncompressed_continuous_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, +#endif + .bFrameIndex = 1, // 1-based index + .bmCapabilities = 0, + .wWidth = FRAME_WIDTH, + .wHeight = FRAME_HEIGHT, + .dwMinBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * 1, + .dwMaxBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * FRAME_RATE, + .dwMaxVideoFrameBufferSize = FRAME_WIDTH * FRAME_HEIGHT * 16 / 8, + .dwDefaultFrameInterval = 10000000 / FRAME_RATE, + .bFrameIntervalType = 0, // continuous + .dwFrameInterval = { + 10000000 / FRAME_RATE, // min + 10000000, // max + 10000000 / FRAME_RATE // step + } + }, + .color = { + .bLength = sizeof(tusb_desc_video_streaming_color_matching_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT, + + .bColorPrimaries = VIDEO_COLOR_PRIMARIES_BT709, + .bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709, + .bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M + }, + +#if USE_ISO_STREAMING + .itf_alt = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING, + .bAlternateSetting = 1, + .bNumEndpoints = 1, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING + }, #endif + + .ep = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + + .bEndpointAddress = EPNUM_VIDEO_IN, + .bmAttributes = { + .xfer = CFG_TUD_VIDEO_STREAMING_BULK ? TUSB_XFER_BULK : TUSB_XFER_ISOCHRONOUS, + .sync = CFG_TUD_VIDEO_STREAMING_BULK ? 0 : 1 // asynchronous + }, + .wMaxPacketSize = CFG_TUD_VIDEO_STREAMING_BULK ? 64 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE, + .bInterval = 1 + } + } }; +#if TUD_OPT_HIGH_SPEED +uvc_cfg_desc_t desc_hs_configuration; + +static uint8_t * get_hs_configuration_desc(void) { + static bool init = false; + + if (!init) { + desc_hs_configuration = desc_fs_configuration; + // change endpoint bulk size to 512 if bulk streaming + if (CFG_TUD_VIDEO_STREAMING_BULK) { + desc_hs_configuration.video_streaming.ep.wMaxPacketSize = 512; + } + } + init = true; + + return (uint8_t *) &desc_hs_configuration; +} + +// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed +tusb_desc_device_qualifier_t const desc_device_qualifier = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, + + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 +}; + +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. +uint8_t const* tud_descriptor_device_qualifier_cb(void) { + return (uint8_t const*) &desc_device_qualifier; +} + +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { + (void) index; // for multiple configurations + // if link speed is high return fullspeed config, and vice versa + if (tud_speed_get() == TUSB_SPEED_HIGH) { + return (uint8_t const*) &desc_fs_configuration; + } else { + return get_hs_configuration_desc(); + } +} +#endif // highspeed + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) -{ +uint8_t const* tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return desc_fs_configuration; +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + if (tud_speed_get() == TUSB_SPEED_HIGH) { + return get_hs_configuration_desc(); + } else +#endif + { + return (uint8_t const*) &desc_fs_configuration; + } } //--------------------------------------------------------------------+ // String Descriptors //--------------------------------------------------------------------+ -// String Descriptor Index -enum { - STRID_LANGID = 0, - STRID_MANUFACTURER, - STRID_PRODUCT, - STRID_SERIAL, -}; - -// array of pointer to string descriptors -char const *string_desc_arr[] = -{ - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - NULL, // 3: Serials will use unique ID if possible - "TinyUSB UVC", // 4: UVC Interface -}; - static uint16_t _desc_str[32 + 1]; // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { (void) langid; size_t chr_count; - switch ( index ) { + switch (index) { case STRID_LANGID: memcpy(&_desc_str[1], string_desc_arr[0], 2); chr_count = 1; @@ -191,17 +461,17 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (index >= sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) return NULL; - const char *str = string_desc_arr[index]; + const char* str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) chr_count = max_count; // Convert ASCII string into UTF-16 - for ( size_t i = 0; i < chr_count; i++ ) { + for (size_t i = 0; i < chr_count; i++) { _desc_str[1 + i] = str[i]; } break; diff --git a/examples/device/video_capture/src/usb_descriptors.h b/examples/device/video_capture/src/usb_descriptors.h index b924c8dbe..12d41b2f3 100644 --- a/examples/device/video_capture/src/usb_descriptors.h +++ b/examples/device/video_capture/src/usb_descriptors.h @@ -27,21 +27,11 @@ #ifndef _USB_DESCRIPTORS_H_ #define _USB_DESCRIPTORS_H_ -/* Time stamp base clock. It is a deprecated parameter. */ -#define UVC_CLOCK_FREQUENCY 27000000 -/* video capture path */ -#define UVC_ENTITY_CAP_INPUT_TERMINAL 0x01 -#define UVC_ENTITY_CAP_OUTPUT_TERMINAL 0x02 - #define FRAME_WIDTH 128 #define FRAME_HEIGHT 96 #define FRAME_RATE 10 -enum { - ITF_NUM_VIDEO_CONTROL, - ITF_NUM_VIDEO_STREAMING, - ITF_NUM_TOTAL -}; +// NOTE: descriptor template is not used but leave here as reference #define TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN (\ TUD_VIDEO_DESC_IAD_LEN\ @@ -126,23 +116,17 @@ enum { #define TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(_stridx, _epin, _width, _height, _fps, _epsize) \ TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ /* Video control 0 */ \ - TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ - TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \ - /* wTotalLength - bLength */ \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \ - UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ - TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\ - /*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\ - /*wObjectiveFocalLength*/0, /*bmControls*/0), \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ /* Video stream alt. 0 */ \ TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 0, _stridx), \ /* Video stream header for without still image capture */ \ TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ - /*wTotalLength - bLength */\ - TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\ - + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\ - + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ /*bmaControls(1)*/0), \ @@ -152,7 +136,7 @@ enum { /* Video stream frame format */ \ TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(/*bFrameIndex */1, 0, _width, _height, \ _width * _height * 16, _width * _height * 16 * _fps, \ - _width * _height * 16, \ + _width * _height * 16 / 8, \ (10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \ /* VS alt 1 */\ @@ -163,23 +147,17 @@ enum { #define TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(_stridx, _epin, _width, _height, _fps, _epsize) \ TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ /* Video control 0 */ \ - TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ - TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \ - /* wTotalLength - bLength */ \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \ - UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ - TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\ - /*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\ - /*wObjectiveFocalLength*/0, /*bmControls*/0), \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ /* Video stream alt. 0 */ \ TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 0, _stridx), \ /* Video stream header for without still image capture */ \ TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ - /*wTotalLength - bLength */\ - TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\ - + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN\ - + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ /*bmaControls(1)*/0), \ @@ -202,22 +180,17 @@ enum { TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ /* Video control 0 */ \ TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ - TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \ - /* wTotalLength - bLength */ \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \ - UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ - TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\ - /*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\ - /*wObjectiveFocalLength*/0, /*bmControls*/0), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ /* Video stream alt. 0 */ \ TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 1, _stridx), \ /* Video stream header for without still image capture */ \ TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ /*wTotalLength - bLength */\ - TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\ - + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\ - + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ /*bmaControls(1)*/0), \ @@ -227,7 +200,7 @@ enum { /* Video stream frame format */ \ TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(/*bFrameIndex */1, 0, _width, _height, \ _width * _height * 16, _width * _height * 16 * _fps, \ - _width * _height * 16, \ + _width * _height * 16 / 8, \ (10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \ TUD_VIDEO_DESC_EP_BULK(_epin, _epsize, 1) @@ -235,23 +208,17 @@ enum { #define TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(_stridx, _epin, _width, _height, _fps, _epsize) \ TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ /* Video control 0 */ \ - TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ - TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \ - /* wTotalLength - bLength */ \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \ - UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ - TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\ - /*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\ - /*wObjectiveFocalLength*/0, /*bmControls*/0), \ - TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ + TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, UVC_ENTITY_CAP_INPUT_TERMINAL, 0), \ /* Video stream alt. 0 */ \ TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 1, _stridx), \ /* Video stream header for without still image capture */ \ TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ - /*wTotalLength - bLength */\ - TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\ - + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN\ - + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ /*bmaControls(1)*/0), \ diff --git a/examples/device/video_capture_2ch/CMakeLists.txt b/examples/device/video_capture_2ch/CMakeLists.txt new file mode 100644 index 000000000..80dc39ca5 --- /dev/null +++ b/examples/device/video_capture_2ch/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.17) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) + +# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT} C CXX ASM) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() +endif() + +add_executable(${PROJECT}) + +if (FORCE_READONLY) +target_compile_definitions(${PROJECT} PRIVATE + CFG_EXAMPLE_VIDEO_READONLY +) +endif() + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c +) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src +) + +# Configure compilation flags and libraries for the example without RTOS. +# See the corresponding function in hw/bsp/FAMILY/family.cmake for details. +family_configure_device_example(${PROJECT} noos) diff --git a/examples/device/video_capture_2ch/Makefile b/examples/device/video_capture_2ch/Makefile new file mode 100644 index 000000000..d698a848d --- /dev/null +++ b/examples/device/video_capture_2ch/Makefile @@ -0,0 +1,18 @@ +include ../../build_system/make/make.mk + +ifeq ($(DISABLE_MJPEG),1) +CFLAGS += -DCFG_EXAMPLE_VIDEO_DISABLE_MJPEG +endif +ifeq ($(FORCE_READONLY),1) +CFLAGS += -DCFG_EXAMPLE_VIDEO_READONLY +endif + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +include ../../build_system/make/rules.mk diff --git a/examples/device/video_capture_2ch/skip.txt b/examples/device/video_capture_2ch/skip.txt new file mode 100644 index 000000000..15c176a2a --- /dev/null +++ b/examples/device/video_capture_2ch/skip.txt @@ -0,0 +1,14 @@ +mcu:MSP430x5xx +mcu:NUC121 +mcu:SAMD11 +mcu:GD32VF103 +mcu:CH32V307 +mcu:STM32L0 +family:espressif +board:curiosity_nano +board:kuiic +board:frdm_k32l2b +board:lpcxpresso11u68 +board:stm32f303disco +board:stm32l412nucleo +board:ek_tm4c123gxl diff --git a/examples/device/video_capture_2ch/src/CMakeLists.txt b/examples/device/video_capture_2ch/src/CMakeLists.txt new file mode 100644 index 000000000..cef2b46ee --- /dev/null +++ b/examples/device/video_capture_2ch/src/CMakeLists.txt @@ -0,0 +1,4 @@ +# This file is for ESP-IDF only +idf_component_register(SRCS "main.c" "usb_descriptors.c" + INCLUDE_DIRS "." + REQUIRES boards tinyusb_src) diff --git a/examples/device/video_capture_2ch/src/images.h b/examples/device/video_capture_2ch/src/images.h new file mode 100644 index 000000000..f0badd074 --- /dev/null +++ b/examples/device/video_capture_2ch/src/images.h @@ -0,0 +1,1934 @@ +#if defined(CFG_EXAMPLE_VIDEO_READONLY) +//--------------------------------------------------------------------+ +// YUY2 Uncompressed Frame (fixed) +//--------------------------------------------------------------------+ +static const unsigned char framebuf_yuy2_readonly[128 * (96 + 1) * 2] = { + /* 0 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 1 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 2 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 3 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 4 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 5 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 6 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 7 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 8 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 9 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 10 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 11 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 12 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 13 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 14 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 15 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 16 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 17 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 18 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 19 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 20 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 21 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 22 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 23 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 24 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 25 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 26 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 27 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 28 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 29 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 30 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 31 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 32 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 33 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 34 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 35 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 36 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 37 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 38 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 39 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 40 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 41 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 42 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 43 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 44 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 45 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 46 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 47 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 48 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 49 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 50 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 51 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 52 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 53 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 54 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 55 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 56 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 57 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 58 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 59 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 60 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 61 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 62 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 63 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 64 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 65 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 66 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 67 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 68 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 69 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 70 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 71 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 72 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 73 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 74 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 75 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 76 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 77 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 78 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 79 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 80 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 81 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 82 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 83 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 84 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 85 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 86 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 87 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 88 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 89 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 90 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 91 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 92 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 93 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 94 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 95 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 96 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, +}; + +#endif + +//--------------------------------------------------------------------+ +// MPEG Compressed Frame (fixed) +//--------------------------------------------------------------------+ + +unsigned char color_bar_0_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x92, 0x8a, 0x00, + 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, + 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, + 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, + 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, + 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, + 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, + 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, + 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, + 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, + 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, + 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, + 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, + 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, + 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, + 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, + 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, + 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, + 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, + 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, + 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, + 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0xff, 0xd9 +}; +unsigned char color_bar_1_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x7d, 0x15, 0x98, + 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, + 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, + 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, + 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, + 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, + 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, + 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, + 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, + 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, + 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, + 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, + 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, + 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, + 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, + 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, + 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, + 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, + 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, + 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, + 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, + 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x7f, 0xff, 0xd9 +}; +unsigned char color_bar_2_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x75, 0x14, 0xcc, + 0xc4, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, + 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, + 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, + 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, + 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, + 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, + 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, + 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, + 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, + 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, + 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, + 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, + 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, + 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, + 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, + 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, + 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, + 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, + 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, + 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, + 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, 0x33, 0xff, 0xd9 +}; +unsigned char color_bar_3_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x5a, 0x2a, 0x08, + 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, + 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, + 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, + 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, + 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, + 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, + 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, + 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, + 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, + 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, + 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, + 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, + 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, + 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, + 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, + 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, + 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, + 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, + 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, + 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, + 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x91, 0xff, 0xd9 +}; +unsigned char color_bar_4_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x4a, 0x2a, 0xcb, + 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, + 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, + 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, + 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, + 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, + 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, + 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, + 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, + 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, + 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, + 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, + 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, + 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, + 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, + 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, + 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, + 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, + 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, + 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, + 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, + 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, 0x9f, 0xff, 0xd9 +}; +unsigned char color_bar_5_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x6d, 0x14, 0x8d, + 0x04, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, + 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, + 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, + 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, + 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, + 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, + 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, + 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, + 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, + 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, + 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, + 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, + 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, + 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, + 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, + 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, + 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, + 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, + 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, + 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, + 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x7f, 0xff, 0xd9 +}; +unsigned char color_bar_6_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x65, 0x15, 0xa0, + 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, + 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, + 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, + 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, + 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, + 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, + 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, + 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, + 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, + 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, + 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, + 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, + 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, + 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, + 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, + 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, + 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, + 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, + 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, + 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, + 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x33, 0xff, 0xd9 +}; +unsigned char color_bar_7_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x8e, 0x8a, 0x00, + 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, + 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, + 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, + 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, + 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, + 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, + 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, + 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, + 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, + 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, + 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, + 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, + 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, + 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, + 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, + 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, + 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, + 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, + 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, + 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, + 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x47, 0xff, 0xd9 +}; diff --git a/examples/device/video_capture_2ch/src/main.c b/examples/device/video_capture_2ch/src/main.c new file mode 100644 index 000000000..e8c2ec6b0 --- /dev/null +++ b/examples/device/video_capture_2ch/src/main.c @@ -0,0 +1,359 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.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 <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "bsp/board_api.h" +#include "tusb.h" +#include "usb_descriptors.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ + +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +void led_blinking_task(void* param); +void usb_device_task(void *param); +void video_task(void* param); + +#if CFG_TUSB_OS == OPT_OS_FREERTOS +void freertos_init_task(void); +#endif + + +//--------------------------------------------------------------------+ +// Main +//--------------------------------------------------------------------+ +int main(void) { + board_init(); + + // If using FreeRTOS: create blinky, tinyusb device, video task +#if CFG_TUSB_OS == OPT_OS_FREERTOS + freertos_init_task(); +#else + // init device stack on configured roothub port + tud_init(BOARD_TUD_RHPORT); + + if (board_init_after_tusb) { + board_init_after_tusb(); + } + + while (1) { + tud_task(); // tinyusb device task + led_blinking_task(NULL); + video_task(NULL); + } +#endif +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) { + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) { + blink_interval_ms = BLINK_NOT_MOUNTED; +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) { + (void) remote_wakeup_en; + blink_interval_ms = BLINK_SUSPENDED; +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) { + blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; +} + +//--------------------------------------------------------------------+ +// USB Video +//--------------------------------------------------------------------+ +#define FRAMEBUF_SIZE (FRAME_WIDTH * FRAME_HEIGHT * 16 / 8) + +static unsigned frame_num[CFG_TUD_VIDEO_STREAMING] = {1}; +static unsigned tx_busy = 0; +static unsigned interval_ms[CFG_TUD_VIDEO_STREAMING] = {1000 / FRAME_RATE}; + +// For mcus that does not have enough SRAM for frame buffer, we use fixed frame data. +// To further reduce the size, we use MJPEG format instead of YUY2. +#include "images.h" + +static struct { + uint32_t size; + uint8_t const *buffer; +} const framebuf_mjpeg[] = { + {sizeof(color_bar_0_jpg), color_bar_0_jpg}, + {sizeof(color_bar_1_jpg), color_bar_1_jpg}, + {sizeof(color_bar_2_jpg), color_bar_2_jpg}, + {sizeof(color_bar_3_jpg), color_bar_3_jpg}, + {sizeof(color_bar_4_jpg), color_bar_4_jpg}, + {sizeof(color_bar_5_jpg), color_bar_5_jpg}, + {sizeof(color_bar_6_jpg), color_bar_6_jpg}, + {sizeof(color_bar_7_jpg), color_bar_7_jpg}, +}; + +#if !defined(CFG_EXAMPLE_VIDEO_READONLY) +// YUY2 frame buffer +static uint8_t framebuf_yuy2[FRAMEBUF_SIZE]; + +static void fill_color_bar(uint8_t* buffer, unsigned start_position) { + /* EBU color bars: https://stackoverflow.com/questions/6939422 */ + static uint8_t const bar_color[8][4] = { + /* Y, U, Y, V */ + { 235, 128, 235, 128}, /* 100% White */ + { 219, 16, 219, 138}, /* Yellow */ + { 188, 154, 188, 16}, /* Cyan */ + { 173, 42, 173, 26}, /* Green */ + { 78, 214, 78, 230}, /* Magenta */ + { 63, 102, 63, 240}, /* Red */ + { 32, 240, 32, 118}, /* Blue */ + { 16, 128, 16, 128}, /* Black */ + }; + uint8_t* p; + + /* Generate the 1st line */ + uint8_t* end = &buffer[FRAME_WIDTH * 2]; + unsigned idx = (FRAME_WIDTH / 2 - 1) - (start_position % (FRAME_WIDTH / 2)); + p = &buffer[idx * 4]; + for (unsigned i = 0; i < 8; ++i) { + for (int j = 0; j < FRAME_WIDTH / (2 * 8); ++j) { + memcpy(p, &bar_color[i], 4); + p += 4; + if (end <= p) { + p = buffer; + } + } + } + + /* Duplicate the 1st line to the others */ + p = &buffer[FRAME_WIDTH * 2]; + for (unsigned i = 1; i < FRAME_HEIGHT; ++i) { + memcpy(p, buffer, FRAME_WIDTH * 2); + p += FRAME_WIDTH * 2; + } +} +#endif + +size_t get_framebuf(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, size_t fnum, void **fb) { + uint32_t idx = ctl_idx + stm_idx; + + if (idx == 0) { + // stream 0 use uncompressed YUY2 frame + #if defined(CFG_EXAMPLE_VIDEO_READONLY) + *fb = (void*)(uintptr_t ) &framebuf_yuy2_readonly[(fnum % (FRAME_WIDTH / 2)) * 4]; + #else + fill_color_bar(framebuf_yuy2, frame_num[idx]); + *fb = framebuf_yuy2; + #endif + + return FRAMEBUF_SIZE; + }else { + // stream 1 use MJPEG frame + size_t const bar_id = fnum & 0x7; + + *fb = (void*)(uintptr_t) framebuf_mjpeg[bar_id].buffer; + return framebuf_mjpeg[bar_id].size; + } +} + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +void video_send_frame(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { + static unsigned start_ms[CFG_TUD_VIDEO_STREAMING] = {0, }; + static unsigned already_sent = 0; + + uint32_t idx = ctl_idx + stm_idx; + if (!tud_video_n_streaming(ctl_idx, stm_idx)) { + already_sent &= ~(1u << idx); + frame_num[idx] = 0; + return; + } + void* fp; + size_t fb_size; + + if (!(already_sent & (1u << idx))) { + already_sent |= 1u << idx; + tx_busy |= 1u << idx; + start_ms[idx] = board_millis(); + + fb_size = get_framebuf(ctl_idx, stm_idx, frame_num[idx], &fp); + tud_video_n_frame_xfer(ctl_idx, stm_idx, fp, fb_size); + } + + unsigned cur = board_millis(); + if (cur - start_ms[idx] < interval_ms[idx]) return; // not enough time + if (tx_busy & (1u << idx)) return; + start_ms[idx] += interval_ms[idx]; + tx_busy |= 1u << idx; + + fb_size = get_framebuf(ctl_idx, stm_idx, frame_num[idx], &fp); + tud_video_n_frame_xfer(ctl_idx, stm_idx, fp, fb_size); +} + + +void video_task(void* param) { + (void) param; + + while(1) { + video_send_frame(0, 0); + video_send_frame(1, 0); + + #if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(interval_ms[0] / portTICK_PERIOD_MS); + #else + return; + #endif + } +} + +void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { + uint32_t idx = ctl_idx + stm_idx; + tx_busy &= ~(1u << idx); + /* flip buffer */ + ++frame_num[idx]; +} + +int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, + video_probe_and_commit_control_t const* parameters) { + uint32_t idx = ctl_idx + stm_idx; + /* convert unit to ms from 100 ns */ + interval_ms[idx] = parameters->dwFrameInterval / 10000; + return VIDEO_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// Blinking Task +//--------------------------------------------------------------------+ +void led_blinking_task(void* param) { + (void) param; + static uint32_t start_ms = 0; + static bool led_state = false; + + while (1) { + #if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + #else + if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + #endif + + start_ms += blink_interval_ms; + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } +} + +//--------------------------------------------------------------------+ +// FreeRTOS +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS + +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define VIDEO_STACK_SIZE (configMINIMAL_STACK_SIZE*4) + +#if TUP_MCU_ESPRESSIF + #define USBD_STACK_SIZE 4096 + int main(void); + void app_main(void) { + main(); + } +#else + // Increase stack size when debug log is enabled + #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) +#endif + +// static task +#if configSUPPORT_STATIC_ALLOCATION +StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StaticTask_t blinky_taskdef; + +StackType_t usb_device_stack[USBD_STACK_SIZE]; +StaticTask_t usb_device_taskdef; + +StackType_t video_stack[VIDEO_STACK_SIZE]; +StaticTask_t video_taskdef; +#endif + +// USB Device Driver task +// This top level thread process all usb events and invoke callbacks +void usb_device_task(void *param) { + (void) param; + + // init device stack on configured roothub port + // This should be called after scheduler/kernel is started. + // Otherwise, it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tud_init(BOARD_TUD_RHPORT); + + if (board_init_after_tusb) { + board_init_after_tusb(); + } + + // RTOS forever loop + while (1) { + // put this thread to waiting state until there is new events + tud_task(); + } +} + +void freertos_init_task(void) { + #if configSUPPORT_STATIC_ALLOCATION + xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); + xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); + xTaskCreateStatic(video_task, "cdc", VIDEO_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, video_stack, &video_taskdef); + #else + xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + xTaskCreate(video_task, "video", VIDEO_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL); + #endif + + // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 + #if !TUP_MCU_ESPRESSIF + vTaskStartScheduler(); + #endif +} +#endif diff --git a/examples/device/video_capture_2ch/src/tusb_config.h b/examples/device/video_capture_2ch/src/tusb_config.h new file mode 100644 index 000000000..43c7dfc90 --- /dev/null +++ b/examples/device/video_capture_2ch/src/tusb_config.h @@ -0,0 +1,120 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.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 _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Board Specific Configuration +//--------------------------------------------------------------------+ + +// RHPort number used for device can be defined by board.mk, default to port 0 +#ifndef BOARD_TUD_RHPORT +#define BOARD_TUD_RHPORT 0 +#endif + +// RHPort max operational speed can defined by board.mk +#ifndef BOARD_TUD_MAX_SPEED +#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED +#endif + +//-------------------------------------------------------------------- +// Common Configuration +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU +#error CFG_TUSB_MCU must be defined +#endif + +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_NONE +#endif + +// Espressif IDF requires "freertos/" prefix in include path +#if TUP_MCU_ESPRESSIF +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG 0 +#endif + +// Enable Device stack +#define CFG_TUD_ENABLED 1 + +// Default is max speed that hardware controller could support with on-chip PHY +#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +// The number of video control interfaces +#define CFG_TUD_VIDEO 2 + +// The number of video streaming interfaces +#define CFG_TUD_VIDEO_STREAMING 2 + +// video streaming endpoint buffer size +#define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE 256 + +// use bulk endpoint for streaming interface +#define CFG_TUD_VIDEO_STREAMING_BULK 1 + +//#define CFG_EXAMPLE_VIDEO_READONLY +//#define CFG_EXAMPLE_VIDEO_DISABLE_MJPEG + +#define CFG_TUD_VIDEO_LOG_LEVEL 1 + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/video_capture_2ch/src/usb_descriptors.c b/examples/device/video_capture_2ch/src/usb_descriptors.c new file mode 100644 index 000000000..e78e452fc --- /dev/null +++ b/examples/device/video_capture_2ch/src/usb_descriptors.c @@ -0,0 +1,653 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.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 "bsp/board_api.h" +#include "tusb.h" +#include "usb_descriptors.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] VIDEO | AUDIO | MIDI | HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VIDEO, 5) | _PID_MAP(VENDOR, 6) ) + +#define USB_VID 0xCafe +#define USB_BCD 0x0200 + +// String Descriptor Index +enum { + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, + STRID_UVC_CONTROL_1, + STRID_UVC_STREAMING_1, + STRID_UVC_CONTROL_2, + STRID_UVC_STREAMING_2, +}; + +// array of pointer to string descriptors +char const* string_desc_arr[] = { + (const char[]) {0x09, 0x04}, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + NULL, // 3: Serials will use unique ID if possible + "UVC Control 1", // 4: UVC Interface 1 + "UVC Streaming 1", // 5: UVC Interface 1 + "UVC Control 2", // 6: UVC Interface 2 + "UVC Streaming 2", // 7: UVC Interface 2 + +}; + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, + + // Use Interface Association Descriptor (IAD) for Video + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = USB_VID, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = STRID_MANUFACTURER, + .iProduct = STRID_PRODUCT, + .iSerialNumber = STRID_SERIAL, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const* tud_descriptor_device_cb(void) { + return (uint8_t const*) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ + +/* Time stamp base clock. It is a deprecated parameter. */ +#define UVC_CLOCK_FREQUENCY 27000000 + +/* video capture path */ +#define UVC_ENTITY_CAP_INPUT_TERMINAL 0x01 +#define UVC_ENTITY_CAP_OUTPUT_TERMINAL 0x02 + +enum { + ITF_NUM_VIDEO_CONTROL_1, + ITF_NUM_VIDEO_STREAMING_1, + ITF_NUM_VIDEO_CONTROL_2, + ITF_NUM_VIDEO_STREAMING_2, + ITF_NUM_TOTAL +}; + +#define EPNUM_VIDEO_IN_1 0x81 +#define EPNUM_VIDEO_IN_2 0x82 + +#if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) + #define USE_MJPEG 1 +#else + #define USE_MJPEG 0 +#endif + +#define USE_ISO_STREAMING (!CFG_TUD_VIDEO_STREAMING_BULK) + +typedef struct TU_ATTR_PACKED { + tusb_desc_interface_t itf; + tusb_desc_video_control_header_1itf_t header; + tusb_desc_video_control_camera_terminal_t camera_terminal; + tusb_desc_video_control_output_terminal_t output_terminal; +} uvc_control_desc_t; + +/* Windows support YUY2 and NV12 + * https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/usb-video-class-driver-overview */ + +typedef struct TU_ATTR_PACKED { + tusb_desc_interface_t itf; + tusb_desc_video_streaming_input_header_1byte_t header; + tusb_desc_video_format_uncompressed_t format; + tusb_desc_video_frame_uncompressed_continuous_t frame; + tusb_desc_video_streaming_color_matching_t color; + +#if USE_ISO_STREAMING + // For ISO streaming, USB spec requires to alternate interface + tusb_desc_interface_t itf_alt; +#endif + + tusb_desc_endpoint_t ep; +} uvc_streaming_yuy2_desc_t; + +typedef struct TU_ATTR_PACKED { + tusb_desc_interface_t itf; + tusb_desc_video_streaming_input_header_1byte_t header; + tusb_desc_video_format_mjpeg_t format; + tusb_desc_video_frame_mjpeg_continuous_t frame; + tusb_desc_video_streaming_color_matching_t color; + +#if USE_ISO_STREAMING + // For ISO streaming, USB spec requires to alternate interface + tusb_desc_interface_t itf_alt; +#endif + + tusb_desc_endpoint_t ep; +} uvc_streaming_mpeg_desc_t; + +typedef struct TU_ATTR_PACKED { + tusb_desc_configuration_t config; + + struct TU_ATTR_PACKED { + tusb_desc_interface_assoc_t iad; + uvc_control_desc_t video_control; + uvc_streaming_yuy2_desc_t video_streaming; + } uvc_yuy2; + + struct TU_ATTR_PACKED { + tusb_desc_interface_assoc_t iad; + uvc_control_desc_t video_control; + uvc_streaming_mpeg_desc_t video_streaming; + } uvc_mpeg; +} uvc_cfg_desc_t; + +const uvc_cfg_desc_t desc_fs_configuration = { + .config = { + .bLength = sizeof(tusb_desc_configuration_t), + .bDescriptorType = TUSB_DESC_CONFIGURATION, + + .wTotalLength = sizeof(uvc_cfg_desc_t), + .bNumInterfaces = ITF_NUM_TOTAL, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = TU_BIT(7), + .bMaxPower = 100 / 2 + }, + //------------- Stream 0: YUY2 -------------// + .uvc_yuy2 = { + .iad = { + .bLength = sizeof(tusb_desc_interface_assoc_t), + .bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION, + + .bFirstInterface = ITF_NUM_VIDEO_CONTROL_1, + .bInterfaceCount = 2, + .bFunctionClass = TUSB_CLASS_VIDEO, + .bFunctionSubClass = VIDEO_SUBCLASS_INTERFACE_COLLECTION, + .bFunctionProtocol = VIDEO_ITF_PROTOCOL_UNDEFINED, + .iFunction = 0 + }, + .video_control = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_CONTROL_1, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_CONTROL, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_CONTROL_1 + }, + .header = { + .bLength = sizeof(tusb_desc_video_control_header_1itf_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_HEADER, + + .bcdUVC = VIDEO_BCD_1_50, + .wTotalLength = sizeof(uvc_control_desc_t) - sizeof(tusb_desc_interface_t), // CS VC descriptors only + .dwClockFrequency = UVC_CLOCK_FREQUENCY, + .bInCollection = 1, + .baInterfaceNr = {ITF_NUM_VIDEO_STREAMING_1} + }, + .camera_terminal = { + .bLength = sizeof(tusb_desc_video_control_camera_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .wTerminalType = VIDEO_ITT_CAMERA, + .bAssocTerminal = 0, + .iTerminal = 0, + .wObjectiveFocalLengthMin = 0, + .wObjectiveFocalLengthMax = 0, + .wOcularFocalLength = 0, + .bControlSize = 3, + .bmControls = {0, 0, 0} + }, + .output_terminal = { + .bLength = sizeof(tusb_desc_video_control_output_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .wTerminalType = VIDEO_TT_STREAMING, + .bAssocTerminal = 0, + .bSourceID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .iTerminal = 0 + } + }, + + .video_streaming = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_1, + .bAlternateSetting = 0, + .bNumEndpoints = CFG_TUD_VIDEO_STREAMING_BULK, // bulk 1, iso 0 + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING_1 + }, + .header = { + .bLength = sizeof(tusb_desc_video_streaming_input_header_1byte_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_INPUT_HEADER, + + .bNumFormats = 1, + .wTotalLength = sizeof(uvc_streaming_yuy2_desc_t) - sizeof(tusb_desc_interface_t) + - sizeof(tusb_desc_endpoint_t) - + (USE_ISO_STREAMING ? sizeof(tusb_desc_interface_t) : 0), // CS VS descriptors only + .bEndpointAddress = EPNUM_VIDEO_IN_1, + .bmInfo = 0, + .bTerminalLink = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .bStillCaptureMethod = 0, + .bTriggerSupport = 0, + .bTriggerUsage = 0, + .bControlSize = 1, + .bmaControls = {0} + }, + .format = { + .bLength = sizeof(tusb_desc_video_format_uncompressed_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, + .bFormatIndex = 1, // 1-based index + .bNumFrameDescriptors = 1, + .guidFormat = {TUD_VIDEO_GUID_YUY2}, + .bBitsPerPixel = 16, + .bDefaultFrameIndex = 1, + .bAspectRatioX = 0, + .bAspectRatioY = 0, + .bmInterlaceFlags = 0, + .bCopyProtect = 0 + }, + .frame = { + .bLength = sizeof(tusb_desc_video_frame_uncompressed_continuous_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, + .bFrameIndex = 1, // 1-based index + .bmCapabilities = 0, + .wWidth = FRAME_WIDTH, + .wHeight = FRAME_HEIGHT, + .dwMinBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * 1, + .dwMaxBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * FRAME_RATE, + .dwMaxVideoFrameBufferSize = FRAME_WIDTH * FRAME_HEIGHT * 16 / 8, + .dwDefaultFrameInterval = 10000000 / FRAME_RATE, + .bFrameIntervalType = 0, // continuous + .dwFrameInterval = { + 10000000 / FRAME_RATE, // min + 10000000, // max + 10000000 / FRAME_RATE // step + } + }, + .color = { + .bLength = sizeof(tusb_desc_video_streaming_color_matching_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT, + + .bColorPrimaries = VIDEO_COLOR_PRIMARIES_BT709, + .bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709, + .bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M + }, + +#if USE_ISO_STREAMING + .itf_alt = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_1, + .bAlternateSetting = 1, + .bNumEndpoints = 1, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING_1 + }, +#endif + .ep = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + + .bEndpointAddress = EPNUM_VIDEO_IN_1, + .bmAttributes = { + .xfer = CFG_TUD_VIDEO_STREAMING_BULK ? TUSB_XFER_BULK : TUSB_XFER_ISOCHRONOUS, + .sync = CFG_TUD_VIDEO_STREAMING_BULK ? 0 : 1 // asynchronous + }, + .wMaxPacketSize = CFG_TUD_VIDEO_STREAMING_BULK ? 64 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE, + .bInterval = 1 + } + } + }, + //------------- Stream 1: MPEG -------------// + .uvc_mpeg = { + .iad = { + .bLength = sizeof(tusb_desc_interface_assoc_t), + .bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION, + + .bFirstInterface = ITF_NUM_VIDEO_CONTROL_2, + .bInterfaceCount = 2, + .bFunctionClass = TUSB_CLASS_VIDEO, + .bFunctionSubClass = VIDEO_SUBCLASS_INTERFACE_COLLECTION, + .bFunctionProtocol = VIDEO_ITF_PROTOCOL_UNDEFINED, + .iFunction = 0 + }, + + .video_control = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_CONTROL_2, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_CONTROL, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_CONTROL_2 + }, + .header = { + .bLength = sizeof(tusb_desc_video_control_header_1itf_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_HEADER, + + .bcdUVC = VIDEO_BCD_1_50, + .wTotalLength = sizeof(uvc_control_desc_t) - sizeof(tusb_desc_interface_t), // CS VC descriptors only + .dwClockFrequency = UVC_CLOCK_FREQUENCY, + .bInCollection = 1, + .baInterfaceNr = { ITF_NUM_VIDEO_STREAMING_2 } + }, + .camera_terminal = { + .bLength = sizeof(tusb_desc_video_control_camera_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .wTerminalType = VIDEO_ITT_CAMERA, + .bAssocTerminal = 0, + .iTerminal = 0, + .wObjectiveFocalLengthMin = 0, + .wObjectiveFocalLengthMax = 0, + .wOcularFocalLength = 0, + .bControlSize = 3, + .bmControls = { 0, 0, 0 } + }, + .output_terminal = { + .bLength = sizeof(tusb_desc_video_control_output_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .wTerminalType = VIDEO_TT_STREAMING, + .bAssocTerminal = 0, + .bSourceID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .iTerminal = 0 + } + }, + + .video_streaming = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_2, + .bAlternateSetting = 0, + .bNumEndpoints = CFG_TUD_VIDEO_STREAMING_BULK, // bulk 1, iso 0 + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING_2 + }, + .header = { + .bLength = sizeof(tusb_desc_video_streaming_input_header_1byte_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_INPUT_HEADER, + + .bNumFormats = 1, + .wTotalLength = sizeof(uvc_streaming_mpeg_desc_t) - sizeof(tusb_desc_interface_t) + - sizeof(tusb_desc_endpoint_t) - (USE_ISO_STREAMING ? sizeof(tusb_desc_interface_t) : 0) , // CS VS descriptors only + .bEndpointAddress = EPNUM_VIDEO_IN_2, + .bmInfo = 0, + .bTerminalLink = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .bStillCaptureMethod = 0, + .bTriggerSupport = 0, + .bTriggerUsage = 0, + .bControlSize = 1, + .bmaControls = { 0 } + }, + .format = { + .bLength = sizeof(tusb_desc_video_format_mjpeg_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_MJPEG, + .bFormatIndex = 1, // 1-based index + .bNumFrameDescriptors = 1, + .bmFlags = 0, + .bDefaultFrameIndex = 1, + .bAspectRatioX = 0, + .bAspectRatioY = 0, + .bmInterlaceFlags = 0, + .bCopyProtect = 0 + }, + .frame = { + .bLength = sizeof(tusb_desc_video_frame_mjpeg_continuous_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_MJPEG, + .bFrameIndex = 1, // 1-based index + .bmCapabilities = 0, + .wWidth = FRAME_WIDTH, + .wHeight = FRAME_HEIGHT, + .dwMinBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * 1, + .dwMaxBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * FRAME_RATE, + .dwMaxVideoFrameBufferSize = FRAME_WIDTH * FRAME_HEIGHT * 16 / 8, + .dwDefaultFrameInterval = 10000000 / FRAME_RATE, + .bFrameIntervalType = 0, // continuous + .dwFrameInterval = { + 10000000 / FRAME_RATE, // min + 10000000, // max + 10000000 / FRAME_RATE // step + } + }, + .color = { + .bLength = sizeof(tusb_desc_video_streaming_color_matching_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT, + + .bColorPrimaries = VIDEO_COLOR_PRIMARIES_BT709, + .bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709, + .bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M + }, + +#if USE_ISO_STREAMING + .itf_alt = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_2, + .bAlternateSetting = 1, + .bNumEndpoints = 1, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING_2 + }, +#endif + .ep = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + + .bEndpointAddress = EPNUM_VIDEO_IN_2, + .bmAttributes = { + .xfer = CFG_TUD_VIDEO_STREAMING_BULK ? TUSB_XFER_BULK : TUSB_XFER_ISOCHRONOUS, + .sync = CFG_TUD_VIDEO_STREAMING_BULK ? 0 : 1 // asynchronous + }, + .wMaxPacketSize = CFG_TUD_VIDEO_STREAMING_BULK ? 64 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE, + .bInterval = 1 + } + } + } +}; + +#if TUD_OPT_HIGH_SPEED +uvc_cfg_desc_t desc_hs_configuration; + +static uint8_t * get_hs_configuration_desc(void) { + static bool init = false; + + if (!init) { + desc_hs_configuration = desc_fs_configuration; + // change endpoint bulk size to 512 if bulk streaming + if (CFG_TUD_VIDEO_STREAMING_BULK) { + desc_hs_configuration.uvc_yuy2.video_streaming.ep.wMaxPacketSize = 512; + desc_hs_configuration.uvc_mpeg.video_streaming.ep.wMaxPacketSize = 512; + } + } + init = true; + + return (uint8_t *) &desc_hs_configuration; +} + +// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed +tusb_desc_device_qualifier_t const desc_device_qualifier = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, + + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 +}; + +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. +uint8_t const* tud_descriptor_device_qualifier_cb(void) { + return (uint8_t const*) &desc_device_qualifier; +} + +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { + (void) index; // for multiple configurations + // if link speed is high return fullspeed config, and vice versa + if (tud_speed_get() == TUSB_SPEED_HIGH) { + return (uint8_t const*) &desc_fs_configuration; + } else { + return get_hs_configuration_desc(); + } +} +#endif // highspeed + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const* tud_descriptor_configuration_cb(uint8_t index) { + (void) index; // for multiple configurations + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + if (tud_speed_get() == TUSB_SPEED_HIGH) { + return get_hs_configuration_desc(); + } else +#endif + { + return (uint8_t const*) &desc_fs_configuration; + } +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +static uint16_t _desc_str[32 + 1]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { + (void) langid; + size_t chr_count; + + switch (index) { + case STRID_LANGID: + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + break; + + case STRID_SERIAL: + chr_count = board_usb_get_serial(_desc_str + 1, 32); + break; + + default: + // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors + + if (index >= sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type + if (chr_count > max_count) chr_count = max_count; + + // Convert ASCII string into UTF-16 + for (size_t i = 0; i < chr_count; i++) { + _desc_str[1 + i] = str[i]; + } + break; + } + + // first byte is length (including header), second byte is string type + _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); + + return _desc_str; +} diff --git a/examples/device/video_capture_2ch/src/usb_descriptors.h b/examples/device/video_capture_2ch/src/usb_descriptors.h new file mode 100644 index 000000000..12d41b2f3 --- /dev/null +++ b/examples/device/video_capture_2ch/src/usb_descriptors.h @@ -0,0 +1,238 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jerzy Kasenbreg + * Copyright (c) 2021 Koji KITAYAMA + * + * 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_DESCRIPTORS_H_ +#define _USB_DESCRIPTORS_H_ + +#define FRAME_WIDTH 128 +#define FRAME_HEIGHT 96 +#define FRAME_RATE 10 + +// NOTE: descriptor template is not used but leave here as reference + +#define TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN (\ + TUD_VIDEO_DESC_IAD_LEN\ + /* control */\ + + TUD_VIDEO_DESC_STD_VC_LEN\ + + (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\ + + TUD_VIDEO_DESC_CAMERA_TERM_LEN\ + + TUD_VIDEO_DESC_OUTPUT_TERM_LEN\ + /* Interface 1, Alternate 0 */\ + + TUD_VIDEO_DESC_STD_VS_LEN\ + + (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\ + + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\ + + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\ + + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\ + /* Interface 1, Alternate 1 */\ + + TUD_VIDEO_DESC_STD_VS_LEN\ + + 7/* Endpoint */\ + ) + +#define TUD_VIDEO_CAPTURE_DESC_MJPEG_LEN (\ + TUD_VIDEO_DESC_IAD_LEN\ + /* control */\ + + TUD_VIDEO_DESC_STD_VC_LEN\ + + (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\ + + TUD_VIDEO_DESC_CAMERA_TERM_LEN\ + + TUD_VIDEO_DESC_OUTPUT_TERM_LEN\ + /* Interface 1, Alternate 0 */\ + + TUD_VIDEO_DESC_STD_VS_LEN\ + + (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\ + + TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\ + + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN\ + + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\ + /* Interface 1, Alternate 1 */\ + + TUD_VIDEO_DESC_STD_VS_LEN\ + + 7/* Endpoint */\ + ) + +#define TUD_VIDEO_CAPTURE_DESC_UNCOMPR_BULK_LEN (\ + TUD_VIDEO_DESC_IAD_LEN\ + /* control */\ + + TUD_VIDEO_DESC_STD_VC_LEN\ + + (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\ + + TUD_VIDEO_DESC_CAMERA_TERM_LEN\ + + TUD_VIDEO_DESC_OUTPUT_TERM_LEN\ + /* Interface 1, Alternate 0 */\ + + TUD_VIDEO_DESC_STD_VS_LEN\ + + (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\ + + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\ + + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\ + + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\ + + 7/* Endpoint */\ + ) + +#define TUD_VIDEO_CAPTURE_DESC_MJPEG_BULK_LEN (\ + TUD_VIDEO_DESC_IAD_LEN\ + /* control */\ + + TUD_VIDEO_DESC_STD_VC_LEN\ + + (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\ + + TUD_VIDEO_DESC_CAMERA_TERM_LEN\ + + TUD_VIDEO_DESC_OUTPUT_TERM_LEN\ + /* Interface 1, Alternate 0 */\ + + TUD_VIDEO_DESC_STD_VS_LEN\ + + (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\ + + TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\ + + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN\ + + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\ + + 7/* Endpoint */\ + ) + +/* Windows support YUY2 and NV12 + * https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/usb-video-class-driver-overview */ + +#define TUD_VIDEO_DESC_CS_VS_FMT_YUY2(_fmtidx, _numfmtdesc, _frmidx, _asrx, _asry, _interlace, _cp) \ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfmtdesc, TUD_VIDEO_GUID_YUY2, 16, _frmidx, _asrx, _asry, _interlace, _cp) +#define TUD_VIDEO_DESC_CS_VS_FMT_NV12(_fmtidx, _numfmtdesc, _frmidx, _asrx, _asry, _interlace, _cp) \ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfmtdesc, TUD_VIDEO_GUID_NV12, 12, _frmidx, _asrx, _asry, _interlace, _cp) +#define TUD_VIDEO_DESC_CS_VS_FMT_M420(_fmtidx, _numfmtdesc, _frmidx, _asrx, _asry, _interlace, _cp) \ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfmtdesc, TUD_VIDEO_GUID_M420, 12, _frmidx, _asrx, _asry, _interlace, _cp) +#define TUD_VIDEO_DESC_CS_VS_FMT_I420(_fmtidx, _numfmtdesc, _frmidx, _asrx, _asry, _interlace, _cp) \ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfmtdesc, TUD_VIDEO_GUID_I420, 12, _frmidx, _asrx, _asry, _interlace, _cp) + +#define TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(_stridx, _epin, _width, _height, _fps, _epsize) \ + TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ + /* Video control 0 */ \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ + TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ + /* Video stream alt. 0 */ \ + TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 0, _stridx), \ + /* Video stream header for without still image capture */ \ + TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ + /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ + /*bmaControls(1)*/0), \ + /* Video stream format */ \ + TUD_VIDEO_DESC_CS_VS_FMT_YUY2(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \ + /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \ + /* Video stream frame format */ \ + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(/*bFrameIndex */1, 0, _width, _height, \ + _width * _height * 16, _width * _height * 16 * _fps, \ + _width * _height * 16 / 8, \ + (10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \ + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \ + /* VS alt 1 */\ + TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 1, 1, _stridx), \ + /* EP */ \ + TUD_VIDEO_DESC_EP_ISO(_epin, _epsize, 1) + +#define TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(_stridx, _epin, _width, _height, _fps, _epsize) \ + TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ + /* Video control 0 */ \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ + TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ + /* Video stream alt. 0 */ \ + TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 0, _stridx), \ + /* Video stream header for without still image capture */ \ + TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ + /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ + /*bmaControls(1)*/0), \ + /* Video stream format */ \ + TUD_VIDEO_DESC_CS_VS_FMT_MJPEG(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \ + /*bmFlags*/0, /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \ + /* Video stream frame format */ \ + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT(/*bFrameIndex */1, 0, _width, _height, \ + _width * _height * 16, _width * _height * 16 * _fps, \ + _width * _height * 16 / 8, \ + (10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \ + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \ + /* VS alt 1 */\ + TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 1, 1, _stridx), \ + /* EP */ \ + TUD_VIDEO_DESC_EP_ISO(_epin, _epsize, 1) + + +#define TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR_BULK(_stridx, _epin, _width, _height, _fps, _epsize) \ + TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ + /* Video control 0 */ \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ + TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ + /* Video stream alt. 0 */ \ + TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 1, _stridx), \ + /* Video stream header for without still image capture */ \ + TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ + /*wTotalLength - bLength */\ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ + /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ + /*bmaControls(1)*/0), \ + /* Video stream format */ \ + TUD_VIDEO_DESC_CS_VS_FMT_YUY2(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \ + /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \ + /* Video stream frame format */ \ + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(/*bFrameIndex */1, 0, _width, _height, \ + _width * _height * 16, _width * _height * 16 * _fps, \ + _width * _height * 16 / 8, \ + (10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \ + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \ + TUD_VIDEO_DESC_EP_BULK(_epin, _epsize, 1) + +#define TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(_stridx, _epin, _width, _height, _fps, _epsize) \ + TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ + /* Video control 0 */ \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ + TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, UVC_ENTITY_CAP_INPUT_TERMINAL, 0), \ + /* Video stream alt. 0 */ \ + TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 1, _stridx), \ + /* Video stream header for without still image capture */ \ + TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ + /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ + /*bmaControls(1)*/0), \ + /* Video stream format */ \ + TUD_VIDEO_DESC_CS_VS_FMT_MJPEG(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \ + /*bmFlags*/0, /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \ + /* Video stream frame format */ \ + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT(/*bFrameIndex */1, 0, _width, _height, \ + _width * _height * 16, _width * _height * 16 * _fps, \ + _width * _height * 16 / 8, \ + (10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \ + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \ + /* EP */ \ + TUD_VIDEO_DESC_EP_BULK(_epin, _epsize, 1) + + +#endif diff --git a/examples/device/webusb_serial/Makefile b/examples/device/webusb_serial/Makefile index 2a3d854fb..7fa475da5 100644 --- a/examples/device/webusb_serial/Makefile +++ b/examples/device/webusb_serial/Makefile @@ -1,4 +1,4 @@ -include ../../make.mk +include ../../build_system/make/make.mk INC += \ src \ @@ -8,4 +8,4 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk +include ../../build_system/make/rules.mk |
