diff --git a/.codespell/exclude-file.txt b/.codespell/exclude-file.txt
deleted file mode 100644
index af8265cc7..000000000
--- a/.codespell/exclude-file.txt
+++ /dev/null
@@ -1 +0,0 @@
- return USB0.INTSTS1.BIT.ATTCH ? true : false;
diff --git a/.codespellrc b/.codespellrc
index 8c32ed706..1f06e0c5c 100644
--- a/.codespellrc
+++ b/.codespellrc
@@ -2,9 +2,9 @@
[codespell]
# In the event of a false positive, add the problematic word, in all lowercase, to 'ignore-words.txt' (one word per line).
# Or copy & paste the whole problematic line to 'exclude-file.txt'
-ignore-words = .codespell/ignore-words.txt
-exclude-file = .codespell/exclude-file.txt
+ignore-words = tools/codespell/ignore-words.txt
+exclude-file = tools/codespell/exclude-file.txt
check-filenames =
check-hidden =
count =
-skip = .cproject,./.git,./hw/mcu,./lib,./examples/*/*/_build,./examples/*/*/ses,./examples/*/*/ozone,./hw/mcu,./test/unit-test/vendor,./tests_obsolete,./tools/uf2
+skip = *.rb,.cproject,.git,./lib,./examples/*/*/_build,./examples/*/*/ses,./examples/*/*/ozone,./hw/mcu,./tests_obsolete
diff --git a/.gitattributes b/.gitattributes
index 2342decc3..140ae8929 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,10 +1,10 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
-*.c text
-*.cpp text
+*.c text
+*.cpp text
*.h text
-*.icf text
+*.icf text
*.js text
*.json text
*.ld text
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 8c39b95e1..d00ee78bd 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -54,21 +54,21 @@ body:
Exact steps in chronological order, details should be specific e.g if you use a command/script to test with, please post it as well.
1. Go to '...'
2. Click on '....'
- 3. See error
+ 3. See error
validations:
required: true
- type: textarea
attributes:
- label: Debug Log as txt file
+ label: Debug Log as txt file (LOG/CFG_TUSB_DEBUG=2)
placeholder: |
Attach your debug log txt file here, where the issue occurred, best with comments to explain the actual events.
-
+
Note1: Please DO NOT paste your lengthy log contents here since it hurts the readability.
- Note2: To enable logging, add `LOG=3` to to the make command if building with stock examples or set `CFG_TUSB_DEBUG=3` in your tusb_config.h.
+ Note2: To enable logging, add `LOG=2` to to the make command if building with stock examples or set `CFG_TUSB_DEBUG=2` in your tusb_config.h.
More information can be found at [example's readme](https://github.com/hathach/tinyusb/blob/master/docs/getting_started.md)
validations:
- required: false
+ required: true
- type: textarea
attributes:
diff --git a/.github/workflows/build_aarch64.yml b/.github/workflows/build_aarch64.yml
index 800a54380..237692498 100644
--- a/.github/workflows/build_aarch64.yml
+++ b/.github/workflows/build_aarch64.yml
@@ -1,6 +1,7 @@
name: Build AArch64
on:
+ workflow_dispatch:
push:
paths:
- 'src/**'
@@ -35,27 +36,18 @@ jobs:
- 'broadcom_64bit'
steps:
- name: Setup Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Checkout TinyUSB
- uses: actions/checkout@v3
-
- - name: Checkout common submodules in lib
- run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip lib/sct_neopixel
-
- - name: Checkout hathach/linkermap
- uses: actions/checkout@v3
- with:
- repository: hathach/linkermap
- path: linkermap
+ uses: actions/checkout@v4
- name: Set Toolchain URL
run: echo >> $GITHUB_ENV TOOLCHAIN_URL=https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz
- name: Cache Toolchain
- uses: actions/cache@v3
+ uses: actions/cache@v4
id: cache-toolchain
with:
path: ~/cache/
@@ -72,15 +64,7 @@ jobs:
run: echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin`
- name: Get Dependencies
- run: python3 tools/get_dependencies.py ${{ matrix.family }}
+ run: python3 tools/get_deps.py ${{ matrix.family }}
- name: Build
- run: python3 tools/build_family.py ${{ matrix.family }}
-
- - name: Linker Map
- run: |
- pip install linkermap/
- for ex in `ls -d examples/device/*/`; do \
- find ${ex} -name *.map -print -quit | \
- xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'; \
- done
+ run: python3 tools/build_make.py ${{ matrix.family }}
diff --git a/.github/workflows/build_arm.yml b/.github/workflows/build_arm.yml
index 96c337462..12e6615ea 100644
--- a/.github/workflows/build_arm.yml
+++ b/.github/workflows/build_arm.yml
@@ -1,12 +1,14 @@
name: Build ARM
on:
+ workflow_dispatch:
push:
paths:
- 'src/**'
- 'examples/**'
- 'lib/**'
- 'hw/**'
+ - 'tools/get_deps.py'
- '.github/workflows/build_arm.yml'
pull_request:
branches: [ master ]
@@ -15,6 +17,7 @@ on:
- 'examples/**'
- 'lib/**'
- 'hw/**'
+ - 'tools/get_deps.py'
- '.github/workflows/build_arm.yml'
concurrency:
@@ -33,32 +36,16 @@ jobs:
family:
# Alphabetical order
- 'broadcom_32bit'
- - 'imxrt'
- - 'lpc15'
- - 'lpc18'
- - 'lpc54'
- - 'lpc55'
- - 'mm32'
- - 'msp432e4'
- - 'nrf'
- - 'rp2040'
- - 'samd11'
- - 'samd21'
- - 'samd51'
- - 'saml2x'
- - 'stm32f0'
- - 'stm32f1'
- - 'stm32f4'
- - 'stm32f7'
- - 'stm32g4'
- - 'stm32h7'
- - 'stm32l4'
- - 'stm32wb'
- - 'tm4c123'
- - 'xmc4000'
+ - 'kinetis_k32l2'
+ - 'lpc11 lpc13 lpc15'
+ - 'lpc51'
+ - 'mm32 msp432e4'
+ - 'samd11 same5x saml2x'
+ - 'stm32l0 stm32wb'
+ - 'tm4c123 xmc4000'
steps:
- name: Setup Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: '3.x'
@@ -68,224 +55,10 @@ jobs:
release: '11.2-2022.02'
- name: Checkout TinyUSB
- uses: actions/checkout@v3
-
- - name: Checkout common submodules in lib
- run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip lib/sct_neopixel
-
- - name: Checkout hathach/linkermap
- uses: actions/checkout@v3
- with:
- repository: hathach/linkermap
- path: linkermap
-
- - name: Checkout pico-sdk for rp2040
- if: matrix.family == 'rp2040'
- run: |
- git clone --depth 1 -b develop https://github.com/raspberrypi/pico-sdk ~/pico-sdk
- echo >> $GITHUB_ENV PICO_SDK_PATH=~/pico-sdk
+ uses: actions/checkout@v4
- name: Get Dependencies
- run: python3 tools/get_dependencies.py ${{ matrix.family }}
+ run: python3 tools/get_deps.py ${{ matrix.family }}
- name: Build
- run: python3 tools/build_family.py ${{ matrix.family }}
-
- - name: Linker Map
- run: |
- pip install linkermap/
- # find -quit to only print linkermap of 1 board per example
- for ex in `ls -d examples/*/*/`
- do
- find ${ex} -name *.map -print -quit | xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'
- done
-
- # Upload binaries for rp2040 hardware test with self-hosted
- - name: Prepare rp2040 Artifacts
- if: matrix.family == 'rp2040' && github.repository_owner == 'hathach'
- run: find examples/ -name "*.elf" -exec mv {} . \;
-
- - name: Upload rp2040 Artifacts
- if: matrix.family == 'rp2040' && github.repository_owner == 'hathach'
- uses: actions/upload-artifact@v3
- with:
- name: ${{ matrix.family }}
- path: |
- *.elf
-
- # Upload binaries for stm32l412nucleo hardware test with self-hosted
- - name: Prepare stm32l412nucleo Artifacts
- if: matrix.family == 'stm32l4'
- run: find examples/ -path "*stm32l412nucleo/*.elf" -exec mv {} . \;
-
- - name: Upload stm32l412nucleo Artifacts
- if: matrix.family == 'stm32l4'
- uses: actions/upload-artifact@v3
- with:
- name: stm32l412nucleo
- path: |
- *.elf
-
- # ---------------------------------------
- # Build all no-family (orphaned) boards
- # disable this workflow since it is often failed randomly
- # ---------------------------------------
- build-board:
- runs-on: ubuntu-latest
- if: false
- strategy:
- fail-fast: false
- matrix:
- example:
- # Alphabetical order, a group of 4
- - 'device/audio_test device/board_test device/cdc_dual_ports device/cdc_msc'
- - 'device/cdc_msc_freertos device/dfu_runtime device/hid_composite device/hid_composite_freertos'
- - 'device/hid_generic_inout device/hid_multiple_interface device/midi_test device/msc_dual_lun'
- - 'device/net_lwip_webserver'
- - 'device/uac2_headset device/usbtmc device/webusb_serial host/cdc_msc_hid'
-
- steps:
- - name: Setup Python
- uses: actions/setup-python@v4
- with:
- python-version: '3.x'
-
- - name: Install ARM GCC
- uses: carlosperate/arm-none-eabi-gcc-action@v1
- with:
- release: '11.2-2022.02'
-
- - name: Checkout TinyUSB
- uses: actions/checkout@v3
-
- - name: Checkout common submodules in lib
- run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip
-
- - name: Build
- run: python3 tools/build_board.py ${{ matrix.example }}
-
- # ---------------------------------------
- # Hardware in the loop (HIL)
- # Current self-hosted instance is running on an RPI4 with
- # - pico + pico-probe connected via USB
- # - pico-probe is /dev/ttyACM0
- # ---------------------------------------
- hw-rp2040-test:
- # run only with hathach's commit due to limited resource on RPI4
- if: github.repository_owner == 'hathach'
- needs: build-arm
- runs-on: [self-hosted, Linux, ARM64, rp2040]
-
- steps:
- - name: Clean workspace
- run: |
- echo "Cleaning up previous run"
- rm -rf "${{ github.workspace }}"
- mkdir -p "${{ github.workspace }}"
-
- - name: Download rp2040 Artifacts
- uses: actions/download-artifact@v3
- with:
- name: rp2040
-
- - name: Create flash.sh
- run: |
- #echo > flash.sh 'cmdout=$(openocd -f "interface/picoprobe.cfg" -f "target/rp2040.cfg" -c "program $1 reset exit")'
- echo > flash.sh 'pyocd flash -t rp2040 $1'
- echo >> flash.sh 'if (( $? )) ; then echo $cmdout ; fi'
- chmod +x flash.sh
-
- - name: Test cdc_dual_ports
- run: |
- ./flash.sh cdc_dual_ports.elf
- while (! ([ -e /dev/ttyACM1 ] && [ -e /dev/ttyACM2 ])) && [ $SECONDS -le 10 ]; do :; done
- test -e /dev/ttyACM1 && echo "ttyACM1 exists"
- test -e /dev/ttyACM2 && echo "ttyACM2 exists"
-
- - name: Test cdc_msc
- run: |
- ./flash.sh cdc_msc.elf
- readme='/media/pi/TinyUSB MSC/README.TXT'
- while (! ([ -e /dev/ttyACM1 ] && [ -f "$readme" ])) && [ $SECONDS -le 10 ]; do :; done
- test -e /dev/ttyACM1 && echo "ttyACM1 exists"
- test -f "$readme" && echo "$readme exists"
- cat "$readme"
-
- - name: Test dfu
- run: |
- ./flash.sh dfu.elf
- while (! (dfu-util -l | grep "Found DFU")) && [ $SECONDS -le 10 ]; do :; done
- dfu-util -d cafe -a 0 -U dfu0
- dfu-util -d cafe -a 1 -U dfu1
- grep "TinyUSB DFU! - Partition 0" dfu0
- grep "TinyUSB DFU! - Partition 1" dfu1
-
- - name: Test dfu_runtime
- run: |
- ./flash.sh dfu_runtime.elf
- while (! (dfu-util -l | grep "Found Runtime")) && [ $SECONDS -le 10 ]; do :; done
-
- # ---------------------------------------
- # Hardware in the loop (HIL)
- # Current self-hosted instance is running on an EPYC 7232 server hosted by HiFiPhile user
- # - STM32L412 Nucleo with on-board jlink as ttyACM0
- # ---------------------------------------
- hw-stm32l412nucleo-test:
- needs: build-arm
- runs-on: [self-hosted, Linux, X64, hifiphile]
-
- steps:
- - name: Clean workspace
- run: |
- echo "Cleaning up previous run"
- rm -rf "${{ github.workspace }}"
- mkdir -p "${{ github.workspace }}"
-
- - name: Download stm32l4 Artifacts
- uses: actions/download-artifact@v3
- with:
- name: stm32l412nucleo
-
- - name: Create flash.sh
- run: |
- echo > flash.sh 'echo halt > flash.jlink'
- echo >> flash.sh 'echo r >> flash.jlink'
- echo >> flash.sh 'echo loadfile $1 >> flash.jlink'
- echo >> flash.sh 'echo r >> flash.jlink'
- echo >> flash.sh 'echo go >> flash.jlink'
- echo >> flash.sh 'echo exit >> flash.jlink'
- echo >> flash.sh 'cmdout=$(JLinkExe -device stm32l412kb -if swd -JTAGConf -1,-1 -speed auto -NoGui 1 -ExitOnError 1 -CommandFile flash.jlink)'
- echo >> flash.sh 'if (( $? )) ; then echo $cmdout ; fi'
- chmod +x flash.sh
-
- - name: Test cdc_dual_ports
- run: |
- ./flash.sh cdc_dual_ports.elf
- while (! ([ -e /dev/ttyACM1 ] && [ -e /dev/ttyACM2 ])) && [ $SECONDS -le 10 ]; do :; done
- test -e /dev/ttyACM1 && echo "ttyACM1 exists"
- test -e /dev/ttyACM2 && echo "ttyACM2 exists"
-
- # Debian does not auto mount usb drive. skip this test for now
- - name: Test cdc_msc
- if: false
- run: |
- ./flash.sh cdc_msc.elf
- readme='/media/pi/TinyUSB MSC/README.TXT'
- while (! ([ -e /dev/ttyACM1 ] && [ -f "$readme" ])) && [ $SECONDS -le 10 ]; do :; done
- test -e /dev/ttyACM1 && echo "ttyACM1 exists"
- test -f "$readme" && echo "$readme exists"
- cat "$readme"
-
- - name: Test dfu
- run: |
- ./flash.sh dfu.elf
- while (! (dfu-util -l | grep "Found DFU")) && [ $SECONDS -le 10 ]; do :; done
- dfu-util -d cafe -a 0 -U dfu0
- dfu-util -d cafe -a 1 -U dfu1
- grep "TinyUSB DFU! - Partition 0" dfu0
- grep "TinyUSB DFU! - Partition 1" dfu1
-
- - name: Test dfu_runtime
- run: |
- ./flash.sh dfu_runtime.elf
- while (! (dfu-util -l | grep "Found Runtime")) && [ $SECONDS -le 10 ]; do :; done
+ run: python3 tools/build_make.py ${{ matrix.family }}
diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml
new file mode 100644
index 000000000..65de47e8d
--- /dev/null
+++ b/.github/workflows/build_cmake.yml
@@ -0,0 +1,292 @@
+name: Build CMake
+
+on:
+ workflow_dispatch:
+ push:
+ paths:
+ - 'src/**'
+ - 'examples/**'
+ - 'lib/**'
+ - 'hw/**'
+ - 'test/hil/**'
+ - 'tools/get_deps.py'
+ - '.github/workflows/build_cmake.yml'
+ pull_request:
+ branches: [ master ]
+ paths:
+ - 'src/**'
+ - 'examples/**'
+ - 'lib/**'
+ - 'hw/**'
+ - 'test/hil/**'
+ - 'tools/get_deps.py'
+ - '.github/workflows/build_cmake.yml'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
+ cancel-in-progress: true
+
+jobs:
+ # ---------------------------------------
+ # Build ARM with GCC
+ # ---------------------------------------
+ arm-gcc:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ family:
+ # Alphabetical order
+ - 'imxrt'
+ - 'kinetis_k kinetis_kl'
+ - 'lpc17 lpc18 lpc40 lpc43'
+ - 'lpc54 lpc55'
+ - 'mcx'
+ - 'nrf'
+ - 'ra'
+ - 'rp2040'
+ - 'samd21'
+ - 'samd51'
+ - 'stm32f0'
+ - 'stm32f1'
+ - 'stm32f2'
+ - 'stm32f3'
+ - 'stm32f4'
+ - 'stm32f7'
+ - 'stm32g0'
+ - 'stm32g4'
+ - 'stm32h5'
+ - 'stm32h7'
+ - 'stm32l4'
+ - 'stm32u5'
+ steps:
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.x'
+
+ - name: Install ARM GCC
+ uses: carlosperate/arm-none-eabi-gcc-action@v1
+ with:
+ release: '12.3.Rel1'
+
+ - name: Checkout TinyUSB
+ uses: actions/checkout@v4
+
+ - name: Checkout pico-sdk for rp2040
+ if: matrix.family == 'rp2040'
+ uses: actions/checkout@v4
+ with:
+ repository: raspberrypi/pico-sdk
+ ref: develop
+ path: pico-sdk
+
+ - name: Get Dependencies
+ run: |
+ sudo apt install -y ninja-build
+ python3 tools/get_deps.py ${{ matrix.family }}
+
+ - name: Build
+ run: python tools/build_cmake.py ${{ matrix.family }} -DCMAKE_BUILD_TYPE=MinSizeRel
+ env:
+ PICO_SDK_PATH: ${{ github.workspace }}/pico-sdk
+
+ - name: Upload Artifacts for Hardware Testing (rp2040)
+ if: matrix.family == 'rp2040' && github.repository_owner == 'hathach'
+ uses: actions/upload-artifact@v4
+ with:
+ name: raspberry_pi_pico
+ path: |
+ cmake-build/cmake-build-raspberry_pi_pico/*/*/*.elf
+
+ - name: Upload Artifacts for Hardware Testing (nRF)
+ if: matrix.family == 'nrf' && github.repository_owner == 'hathach'
+ uses: actions/upload-artifact@v4
+ with:
+ name: feather_nrf52840_express
+ path: |
+ cmake-build/cmake-build-feather_nrf52840_express/*/*/*.elf
+
+ - name: Upload Artifacts for Hardware Testing (samd51)
+ if: matrix.family == 'samd51' && github.repository_owner == 'hathach'
+ uses: actions/upload-artifact@v4
+ with:
+ name: itsybitsy_m4
+ path: |
+ cmake-build/cmake-build-itsybitsy_m4/*/*/*.bin
+
+ # ---------------------------------------
+ # Build ARM with Clang
+ # ---------------------------------------
+ arm-clang:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ family:
+ # Alphabetical order
+ - 'imxrt'
+ - 'kinetis_k kinetis_kl'
+ - 'lpc17 lpc18 lpc40 lpc43'
+ - 'lpc54 lpc55'
+ #- 'mcx' not working with gcc anymore, need to fix this first
+ - 'nrf'
+ #- 'ra' port later
+ #- 'rp2040' port later
+ - 'samd21'
+ - 'samd51'
+ - 'stm32f0'
+ - 'stm32f1'
+ - 'stm32f2'
+ - 'stm32f3'
+ - 'stm32f4'
+ - 'stm32f7'
+ - 'stm32g0'
+ - 'stm32g4'
+ - 'stm32h5'
+ - 'stm32h7'
+ - 'stm32l4'
+ - 'stm32u5'
+ steps:
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.x'
+
+ - name: Checkout TinyUSB
+ uses: actions/checkout@v4
+
+ - name: Checkout pico-sdk for rp2040
+ if: matrix.family == 'rp2040'
+ uses: actions/checkout@v4
+ with:
+ repository: raspberrypi/pico-sdk
+ ref: develop
+ path: pico-sdk
+
+ - name: Set Toolchain URL
+ run: echo >> $GITHUB_ENV TOOLCHAIN_URL=https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-17.0.1/LLVMEmbeddedToolchainForArm-17.0.1-Linux-x86_64.tar.xz
+
+ - name: Cache Toolchain
+ uses: actions/cache@v4
+ id: cache-toolchain
+ with:
+ path: ~/cache/
+ key: ${{ runner.os }}-24-04-17-${{ env.TOOLCHAIN_URL }}
+
+ - name: Install Toolchain
+ if: steps.cache-toolchain.outputs.cache-hit != 'true'
+ run: |
+ mkdir -p ~/cache/toolchain
+ wget --progress=dot:mega $TOOLCHAIN_URL -O toolchain.tar.xz
+ tar -C ~/cache/toolchain -xaf toolchain.tar.xz
+
+ - name: Prepare to build
+ run: |
+ echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin`
+ sudo apt install -y ninja-build
+ python3 tools/get_deps.py ${{ matrix.family }}
+
+ - name: Build
+ run: python tools/build_cmake.py ${{ matrix.family }} -DTOOLCHAIN=clang -DCMAKE_BUILD_TYPE=MinSizeRel
+ env:
+ PICO_SDK_PATH: ${{ github.workspace }}/pico-sdk
+
+ # ---------------------------------------
+ # Build MSP430 with GCC
+ # ---------------------------------------
+ msp430-gcc:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ family:
+ # Alphabetical order
+ - 'msp430'
+ steps:
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.x'
+
+ - name: Checkout TinyUSB
+ uses: actions/checkout@v4
+
+ - name: Set Toolchain URL
+ run: echo >> $GITHUB_ENV TOOLCHAIN_URL=http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2
+
+ - name: Cache Toolchain
+ uses: actions/cache@v4
+ id: cache-toolchain
+ with:
+ path: ~/cache/
+ key: ${{ runner.os }}-24-04-17-${{ env.TOOLCHAIN_URL }}
+
+ - name: Install Toolchain
+ if: steps.cache-toolchain.outputs.cache-hit != 'true'
+ run: |
+ mkdir -p ~/cache/toolchain
+ wget --progress=dot:mega $TOOLCHAIN_URL -O toolchain.tar.bz2
+ tar -C ~/cache/toolchain -xaf toolchain.tar.bz2
+
+ - name: Prepare to build
+ run: |
+ echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin`
+ sudo apt install -y ninja-build
+ python3 tools/get_deps.py ${{ matrix.family }}
+
+ - name: Build
+ run: python tools/build_cmake.py ${{ matrix.family }} -DCMAKE_BUILD_TYPE=MinSizeRel
+
+ # ---------------------------------------
+ # Hardware in the loop (HIL)
+ # Current self-hosted instance is running on an RPI4. For attached hardware checkout hil_pi4.json
+ # ---------------------------------------
+ hil-test:
+ # run only with hathach's commit due to limited resource on RPI4
+ if: github.repository_owner == 'hathach'
+ needs: arm-gcc
+ runs-on: [self-hosted, rp2040, nrf52840, hardware-in-the-loop]
+ strategy:
+ fail-fast: false
+ matrix:
+ board:
+ - 'feather_nrf52840_express'
+ - 'itsybitsy_m4'
+ - 'raspberry_pi_pico'
+ steps:
+ - name: Clean workspace
+ run: |
+ echo "Cleaning up previous run"
+ rm -rf "${{ github.workspace }}"
+ mkdir -p "${{ github.workspace }}"
+
+ # USB bus on rpi4 is not stable, reset it before testing
+ - name: Reset USB bus
+ run: |
+ lsusb
+ lsusb -t
+ # reset VIA Labs 2.0 hub
+ sudo usbreset 001/002
+
+ # legacy code
+ #for port in $(lspci | grep USB | cut -d' ' -f1); do
+ # echo -n "0000:${port}"| sudo tee /sys/bus/pci/drivers/xhci_hcd/unbind;
+ # sleep 0.1;
+ # echo -n "0000:${port}" | sudo tee /sys/bus/pci/drivers/xhci_hcd/bind;
+ #done
+
+ - name: Checkout test/hil
+ uses: actions/checkout@v4
+ with:
+ sparse-checkout: test/hil
+
+ - name: Download Artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: ${{ matrix.board }}
+ path: cmake-build/cmake-build-${{ matrix.board }}
+
+ - name: Test on actual hardware
+ run: |
+ python3 test/hil/hil_test.py --board ${{ matrix.board }} hil_pi4.json
diff --git a/.github/workflows/build_esp.yml b/.github/workflows/build_esp.yml
index dbc51a60f..4108a58a5 100644
--- a/.github/workflows/build_esp.yml
+++ b/.github/workflows/build_esp.yml
@@ -1,12 +1,14 @@
name: Build ESP
on:
+ workflow_dispatch:
push:
paths:
- 'src/**'
- 'examples/**'
- 'lib/**'
- 'hw/**'
+ - 'test/hil/**'
- '.github/workflows/build_esp.yml'
pull_request:
branches: [ master ]
@@ -15,6 +17,7 @@ on:
- 'examples/**'
- 'lib/**'
- 'hw/**'
+ - 'test/hil/**'
- '.github/workflows/build_esp.yml'
concurrency:
@@ -28,16 +31,13 @@ jobs:
fail-fast: false
matrix:
board:
- # Alphabetical order
# ESP32-S2
- - 'espressif_saola_1'
+ - 'espressif_kaluga_1'
# ESP32-S3
- #- 'espressif_s3_devkitm'
- # S3 compile error with "dangerous relocation: call8: call target out of range: memcpy"
-
+ - 'espressif_s3_devkitm'
steps:
- name: Setup Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: '3.x'
@@ -45,22 +45,70 @@ jobs:
run: docker pull espressif/idf:latest
- name: Checkout TinyUSB
- uses: actions/checkout@v3
-
- - name: Checkout hathach/linkermap
- uses: actions/checkout@v3
- with:
- repository: hathach/linkermap
- path: linkermap
+ uses: actions/checkout@v4
- name: Build
- run: docker run --rm -v $PWD:/project -w /project espressif/idf:latest python3 tools/build_esp32sx.py ${{ matrix.board }}
+ run: docker run --rm -v $PWD:/project -w /project espressif/idf:v5.1.1 python3 tools/build_esp32.py ${{ matrix.board }}
- - name: Linker Map
- run: |
- pip install linkermap/
- # find -quit to only print linkermap of 1 board per example
- for ex in `ls -d examples/device/*/`
- do
- find ${ex} -maxdepth 3 -name *.map -print -quit | xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'
- done
+ - name: Upload Artifacts for Hardware Testing
+ if: matrix.board == 'espressif_s3_devkitm' && github.repository_owner == 'hathach'
+ uses: actions/upload-artifact@v4
+ with:
+ name: ${{ matrix.board }}
+ path: |
+ cmake-build/cmake-build-${{ matrix.board }}/*/*/bootloader/bootloader.bin
+ cmake-build/cmake-build-${{ matrix.board }}/*/*/*.bin
+ cmake-build/cmake-build-${{ matrix.board }}/*/*/partition_table/partition-table.bin
+ cmake-build/cmake-build-${{ matrix.board }}/*/*/config.env
+ cmake-build/cmake-build-${{ matrix.board }}/*/*/flash_args
+
+ # ---------------------------------------
+ # Hardware in the loop (HIL)
+ # Current self-hosted instance is running on an RPI4. For attached hardware checkout hil_pi4.json
+ # ---------------------------------------
+ hil-test:
+ # run only with hathach's commit due to limited resource on RPI4
+ if: github.repository_owner == 'hathach'
+ needs: build-esp
+ runs-on: [self-hosted, esp32s3, hardware-in-the-loop]
+ strategy:
+ fail-fast: false
+ matrix:
+ board:
+ - 'espressif_s3_devkitm'
+ steps:
+ - name: Clean workspace
+ run: |
+ echo "Cleaning up previous run"
+ rm -rf "${{ github.workspace }}"
+ mkdir -p "${{ github.workspace }}"
+
+ # USB bus on rpi4 is not stable, reset it before testing
+ - name: Reset USB bus
+ run: |
+ lsusb
+ lsusb -t
+ # reset VIA Labs 2.0 hub
+ sudo usbreset 001/002
+
+ # legacy code
+ #for port in $(lspci | grep USB | cut -d' ' -f1); do
+ # echo -n "0000:${port}"| sudo tee /sys/bus/pci/drivers/xhci_hcd/unbind;
+ # sleep 0.1;
+ # echo -n "0000:${port}" | sudo tee /sys/bus/pci/drivers/xhci_hcd/bind;
+ #done
+
+ - name: Checkout test/hil
+ uses: actions/checkout@v4
+ with:
+ sparse-checkout: test/hil
+
+ - name: Download Artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: ${{ matrix.board }}
+ path: cmake-build/cmake-build-${{ matrix.board }}
+
+ - name: Test on actual hardware
+ run: |
+ python3 test/hil/hil_test.py --board ${{ matrix.board }} hil_pi4.json
diff --git a/.github/workflows/build_iar.yml b/.github/workflows/build_iar.yml
index 33e77c3dc..499349904 100644
--- a/.github/workflows/build_iar.yml
+++ b/.github/workflows/build_iar.yml
@@ -1,12 +1,15 @@
name: Build IAR
on:
+ workflow_dispatch:
push:
paths:
- 'src/**'
- 'examples/**'
- 'lib/**'
- 'hw/**'
+ - 'tools/get_deps.py'
+ - 'test/hil/**'
- '.github/workflows/build_iar.yml'
pull_request:
branches: [ master ]
@@ -15,6 +18,8 @@ on:
- 'examples/**'
- 'lib/**'
- 'hw/**'
+ - 'tools/get_deps.py'
+ - 'test/hil/**'
- '.github/workflows/build_iar.yml'
concurrency:
@@ -22,36 +27,33 @@ concurrency:
cancel-in-progress: true
jobs:
- build-arm:
+ cmake:
+ if: github.repository_owner == 'hathach'
runs-on: [self-hosted, Linux, X64, hifiphile]
strategy:
fail-fast: false
matrix:
family:
- # Alphabetical order
- # Note: bundle multiple families into a matrix since there is only one self-hosted instance can
- # run IAR build. Too many matrix can hurt due to setup/teardown overhead.
- - 'stm32f0 stm32f1 stm32f4 stm32f7 stm32g4 stm32h7 stm32l4'
+ # Alphabetical order
+ # Note: bundle multiple families into a matrix since there is only one self-hosted instance can
+ # run IAR build. Too many matrix can hurt due to setup/teardown overhead.
+ - 'lpc43 stm32f0 stm32f1 stm32f7 stm32g0 stm32g4 stm32l4'
steps:
- - name: Clean workspace
- run: |
- echo "Cleaning up previous run"
- rm -rf "${{ github.workspace }}"
- mkdir -p "${{ github.workspace }}"
+ - name: Clean workspace
+ run: |
+ echo "Cleaning up previous run"
+ rm -rf "${{ github.workspace }}"
+ mkdir -p "${{ github.workspace }}"
- - name: Checkout TinyUSB
- uses: actions/checkout@v3
+ - name: Checkout TinyUSB
+ uses: actions/checkout@v4
- - name: Checkout submodules and dependencies
- run: |
- git submodule update --init lib/FreeRTOS-Kernel lib/lwip lib/sct_neopixel
- python3 tools/get_dependencies.py ${{ matrix.family }}
+ - name: Get Dependencies
+ run: python3 tools/get_deps.py ${{ matrix.family }}
- #- name: Checkout pico-sdk for rp2040
- # if: matrix.family == 'rp2040'
- # run: |
- # git clone --depth 1 -b develop https://github.com/raspberrypi/pico-sdk ~/pico-sdk
- # echo >> $GITHUB_ENV PICO_SDK_PATH=~/pico-sdk
+ - name: Build
+ run: python3 tools/build_cmake.py ${{ matrix.family }} -DTOOLCHAIN=iar -DCMAKE_BUILD_TYPE=MinSizeRel
- - name: Build
- run: python3 tools/build_family.py ${{ matrix.family }} CC=iccarm
+ - name: Test on actual hardware (hardware in the loop)
+ run: |
+ python3 test/hil/hil_test.py hil_hfp.json
diff --git a/.github/workflows/build_msp430.yml b/.github/workflows/build_msp430.yml
deleted file mode 100644
index 2c7785806..000000000
--- a/.github/workflows/build_msp430.yml
+++ /dev/null
@@ -1,85 +0,0 @@
-name: Build MSP430
-
-on:
- push:
- paths:
- - 'src/**'
- - 'examples/**'
- - 'lib/**'
- - 'hw/**'
- - '.github/workflows/build_msp430.yml'
- pull_request:
- branches: [ master ]
- paths:
- - 'src/**'
- - 'examples/**'
- - 'lib/**'
- - 'hw/**'
- - '.github/workflows/build_msp430.yml'
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
- cancel-in-progress: true
-
-jobs:
- build-msp430:
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- family:
- # Alphabetical order
- - 'msp430'
-
- steps:
- - name: Setup Python
- uses: actions/setup-python@v4
- with:
- python-version: '3.x'
-
- - name: Checkout TinyUSB
- uses: actions/checkout@v3
-
- - name: Checkout common submodules in lib
- run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip
-
- - name: Checkout hathach/linkermap
- uses: actions/checkout@v3
- with:
- repository: hathach/linkermap
- path: linkermap
-
- - name: Set Toolchain URL
- run: echo >> $GITHUB_ENV TOOLCHAIN_URL=http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2
-
- - name: Cache Toolchain
- uses: actions/cache@v3
- id: cache-toolchain
- with:
- path: ~/cache/
- key: ${{ runner.os }}-21-03-04-${{ env.TOOLCHAIN_URL }}
-
- - name: Install Toolchain
- if: steps.cache-toolchain.outputs.cache-hit != 'true'
- run: |
- mkdir -p ~/cache/toolchain
- wget --progress=dot:mega $TOOLCHAIN_URL -O toolchain.tar.bz2
- tar -C ~/cache/toolchain -xaf toolchain.tar.bz2
-
- - name: Set Toolchain Path
- run: echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin`
-
- - name: Get Dependencies
- run: python3 tools/get_dependencies.py ${{ matrix.family }}
-
- - name: Build
- run: python3 tools/build_family.py ${{ matrix.family }}
-
- - name: Linker Map
- run: |
- pip install linkermap/
- # find -quit to only print linkermap of 1 board per example
- for ex in `ls -d examples/device/*/`
- do
- find ${ex} -name *.map -print -quit | xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'
- done
diff --git a/.github/workflows/build_renesas.yml b/.github/workflows/build_renesas.yml
index 3a961d327..fbc12d285 100644
--- a/.github/workflows/build_renesas.yml
+++ b/.github/workflows/build_renesas.yml
@@ -1,12 +1,14 @@
name: Build Renesas
on:
+ workflow_dispatch:
push:
paths:
- 'src/**'
- 'examples/**'
- 'lib/**'
- 'hw/**'
+ - 'tools/get_deps.py'
- '.github/workflows/build_renesas.yml'
pull_request:
branches: [ master ]
@@ -15,6 +17,7 @@ on:
- 'examples/**'
- 'lib/**'
- 'hw/**'
+ - 'tools/get_deps.py'
- '.github/workflows/build_renesas.yml'
concurrency:
@@ -32,27 +35,18 @@ jobs:
- 'rx'
steps:
- name: Setup Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Checkout TinyUSB
- uses: actions/checkout@v3
-
- - name: Checkout common submodules in lib
- run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip
-
- - name: Checkout hathach/linkermap
- uses: actions/checkout@v3
- with:
- repository: hathach/linkermap
- path: linkermap
+ uses: actions/checkout@v4
- name: Set Toolchain URL
run: echo >> $GITHUB_ENV TOOLCHAIN_URL=http://gcc-renesas.com/downloads/get.php?f=rx/8.3.0.202004-gnurx/gcc-8.3.0.202004-GNURX-ELF.run
- name: Cache Toolchain
- uses: actions/cache@v3
+ uses: actions/cache@v4
id: cache-toolchain
with:
path: ~/cache/
@@ -70,16 +64,7 @@ jobs:
run: echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin`
- name: Get Dependencies
- run: python3 tools/get_dependencies.py ${{ matrix.family }}
+ run: python3 tools/get_deps.py ${{ matrix.family }}
- name: Build
- run: python3 tools/build_family.py ${{ matrix.family }}
-
- - name: Linker Map
- run: |
- pip install linkermap/
- # find -quit to only print linkermap of 1 board per example
- for ex in `ls -d examples/device/*/`
- do
- find ${ex} -name *.map -print -quit | xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'
- done
+ run: python3 tools/build_make.py ${{ matrix.family }}
diff --git a/.github/workflows/build_riscv.yml b/.github/workflows/build_riscv.yml
index fb4d4d28c..7f5031ff1 100644
--- a/.github/workflows/build_riscv.yml
+++ b/.github/workflows/build_riscv.yml
@@ -1,12 +1,14 @@
name: Build RISC-V
on:
+ workflow_dispatch:
push:
paths:
- 'src/**'
- 'examples/**'
- 'lib/**'
- 'hw/**'
+ - 'tools/get_deps.py'
- '.github/workflows/build_riscv.yml'
pull_request:
branches: [ master ]
@@ -15,6 +17,7 @@ on:
- 'examples/**'
- 'lib/**'
- 'hw/**'
+ - 'tools/get_deps.py'
- '.github/workflows/build_riscv.yml'
concurrency:
@@ -34,27 +37,18 @@ jobs:
- 'gd32vf103'
steps:
- name: Setup Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Checkout TinyUSB
- uses: actions/checkout@v3
-
- - name: Checkout common submodules in lib
- run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip
-
- - name: Checkout hathach/linkermap
- uses: actions/checkout@v3
- with:
- repository: hathach/linkermap
- path: linkermap
+ uses: actions/checkout@v4
- name: Set Toolchain URL
run: echo >> $GITHUB_ENV TOOLCHAIN_URL=https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v10.1.0-1.1/xpack-riscv-none-embed-gcc-10.1.0-1.1-linux-x64.tar.gz
- name: Cache Toolchain
- uses: actions/cache@v3
+ uses: actions/cache@v4
id: cache-toolchain
with:
path: ~/cache/
@@ -71,16 +65,7 @@ jobs:
run: echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin`
- name: Get Dependencies
- run: python3 tools/get_dependencies.py ${{ matrix.family }}
+ run: python3 tools/get_deps.py ${{ matrix.family }}
- name: Build
- run: python3 tools/build_family.py ${{ matrix.family }}
-
- - name: Linker Map
- run: |
- pip install linkermap/
- # find -quit to only print linkermap of 1 board per example
- for ex in `ls -d examples/device/*/`
- do
- find ${ex} -name *.map -print -quit | xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'
- done
+ run: python3 tools/build_make.py ${{ matrix.family }}
diff --git a/.github/workflows/build_win_mac.yml b/.github/workflows/build_win_mac.yml
new file mode 100644
index 000000000..b33b5b593
--- /dev/null
+++ b/.github/workflows/build_win_mac.yml
@@ -0,0 +1,54 @@
+name: Build Windows/MacOS
+
+on:
+ workflow_dispatch:
+ push:
+ paths:
+ - 'src/**'
+ - 'examples/**'
+ - 'lib/**'
+ - 'hw/**'
+ - '.github/workflows/build_win_mac.yml'
+ pull_request:
+ branches: [ master ]
+ paths:
+ - 'src/**'
+ - 'examples/**'
+ - 'lib/**'
+ - 'hw/**'
+ - '.github/workflows/build_win_mac.yml'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
+ cancel-in-progress: true
+
+jobs:
+ # ---------------------------------------
+ # Build ARM family
+ # ---------------------------------------
+ build-arm:
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [windows-latest, macos-latest]
+ runs-on: ${{ matrix.os }}
+
+ steps:
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.x'
+
+ - name: Install ARM GCC
+ uses: carlosperate/arm-none-eabi-gcc-action@v1
+ with:
+ release: '10.3-2021.10'
+
+ - name: Checkout TinyUSB
+ uses: actions/checkout@v4
+
+ - name: Get Dependencies
+ run: python3 tools/get_deps.py stm32f4
+
+ - name: Build
+ run: python3 tools/build_make.py stm32f4 stm32f411disco
diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml
index 7314fd9e6..5dc0f2764 100644
--- a/.github/workflows/cifuzz.yml
+++ b/.github/workflows/cifuzz.yml
@@ -1,5 +1,6 @@
name: CIFuzz
on:
+ workflow_dispatch:
pull_request:
branches:
- master
@@ -26,7 +27,7 @@ jobs:
language: c++
fuzz-seconds: 600
- name: Upload Crash
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
diff --git a/.github/workflows/codeql-buildscript.sh b/.github/workflows/codeql-buildscript.sh
new file mode 100644
index 000000000..35e029922
--- /dev/null
+++ b/.github/workflows/codeql-buildscript.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+FAMILY=stm32l4
+python3 tools/get_deps.py $FAMILY
+python3 tools/build_make.py $FAMILY
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 000000000..1f7b60b9c
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,137 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL"
+
+on:
+ push:
+ branches: [ 'master' ]
+ paths:
+ - 'src/**'
+ - 'examples/**'
+ - 'lib/**'
+ - 'hw/**'
+ - '.github/workflows/codeql.yml'
+ pull_request:
+ branches: [ 'master' ]
+ paths:
+ - 'src/**'
+ - 'examples/**'
+ - 'lib/**'
+ - 'hw/**'
+ - '.github/workflows/codeql.yml'
+ schedule:
+ - cron: '0 0 * * *'
+
+jobs:
+ analyze:
+ name: Analyze
+ # Runner size impacts CodeQL analysis time. To learn more, please see:
+ # - https://gh.io/recommended-hardware-resources-for-running-codeql
+ # - https://gh.io/supported-runners-and-hardware-resources
+ # - https://gh.io/using-larger-runners
+ # Consider using larger runners for possible analysis time improvements.
+ runs-on: ubuntu-latest
+ timeout-minutes: 360
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'c-cpp' ]
+ # CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ]
+ # Use only 'java-kotlin' to analyze code written in Java, Kotlin or both
+ # Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
+ # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Install ARM GCC
+ uses: carlosperate/arm-none-eabi-gcc-action@v1
+ with:
+ release: '11.2-2022.02'
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: ${{ matrix.language }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+
+ # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+ # queries: security-extended,security-and-quality
+ queries: security-and-quality
+
+
+ # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ #- name: Autobuild
+ # uses: github/codeql-action/autobuild@v2
+
+ # âšī¸ Command-line programs to run using the OS shell.
+ # đ See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+
+ # If the Autobuild fails above, remove it and uncomment the following three lines.
+ # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
+
+ - run: |
+ ./.github/workflows/codeql-buildscript.sh
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
+ with:
+ category: "/language:${{matrix.language}}"
+ upload: false
+ id: step1
+
+ # Filter out rules with low severity or high false positive rate
+ # Also filter out warnings in third-party code
+ - name: Filter out unwanted errors and warnings
+ uses: advanced-security/filter-sarif@v1
+ with:
+ patterns: |
+ -**:cpp/path-injection
+ -**:cpp/world-writable-file-creation
+ -**:cpp/poorly-documented-function
+ -**:cpp/potentially-dangerous-function
+ -**:cpp/use-of-goto
+ -**:cpp/integer-multiplication-cast-to-long
+ -**:cpp/comparison-with-wider-type
+ -**:cpp/leap-year/*
+ -**:cpp/ambiguously-signed-bit-field
+ -**:cpp/suspicious-pointer-scaling
+ -**:cpp/suspicious-pointer-scaling-void
+ -**:cpp/unsigned-comparison-zero
+ -**/third*party/**
+ -**/3rd*party/**
+ -**/external/**
+ input: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif
+ output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif
+
+ - name: Upload SARIF
+ uses: github/codeql-action/upload-sarif@v2
+ with:
+ sarif_file: ${{ steps.step1.outputs.sarif-output }}
+ category: "/language:${{matrix.language}}"
+
+ - name: Archive CodeQL results
+ uses: actions/upload-artifact@v4
+ with:
+ name: codeql-results
+ path: ${{ steps.step1.outputs.sarif-output }}
+ retention-days: 5
diff --git a/.github/workflows/fail_on_error.py b/.github/workflows/fail_on_error.py
new file mode 100755
index 000000000..29791742b
--- /dev/null
+++ b/.github/workflows/fail_on_error.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+
+import json
+import sys
+
+# Return whether SARIF file contains error-level results
+def codeql_sarif_contain_error(filename):
+ with open(filename, 'r') as f:
+ s = json.load(f)
+
+ for run in s.get('runs', []):
+ rules_metadata = run['tool']['driver']['rules']
+ if not rules_metadata:
+ rules_metadata = run['tool']['extensions'][0]['rules']
+
+ for res in run.get('results', []):
+ if 'ruleIndex' in res:
+ rule_index = res['ruleIndex']
+ elif 'rule' in res and 'index' in res['rule']:
+ rule_index = res['rule']['index']
+ else:
+ continue
+ try:
+ rule_level = rules_metadata[rule_index]['defaultConfiguration']['level']
+ except IndexError as e:
+ print(e, rule_index, len(rules_metadata))
+ else:
+ if rule_level == 'error':
+ return True
+ return False
+
+if __name__ == "__main__":
+ if codeql_sarif_contain_error(sys.argv[1]):
+ sys.exit(1)
diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml
new file mode 100644
index 000000000..c3cc59d0d
--- /dev/null
+++ b/.github/workflows/labeler.yml
@@ -0,0 +1,73 @@
+name: Labeler
+
+on:
+ issues:
+ types: [opened]
+ pull_request_target:
+ types: [opened]
+
+jobs:
+ label-priority:
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ pull-requests: write
+ steps:
+ - name: Label New Issue or PR
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ let label = '';
+ let username = '';
+ let issueOrPrNumber = 0;
+
+ if (context.eventName === 'issues') {
+ username = context.payload.issue.user.login;
+ issueOrPrNumber = context.payload.issue.number;
+ } else if (context.eventName === 'pull_request_target') {
+ username = context.payload.pull_request.user.login;
+ issueOrPrNumber = context.payload.pull_request.number;
+ }
+
+ // Check if an Adafruit member
+ try {
+ const adafruitResponse = await github.rest.orgs.checkMembershipForUser({
+ org: 'adafruit',
+ username: username
+ });
+
+ if (adafruitResponse.status === 204) {
+ console.log('Adafruit Member');
+ label = 'Prio Urgent';
+ }
+ } catch (error) {
+ console.log('Not an Adafruit member');
+ }
+
+ // Check if a contributor
+ if (label == '') {
+ try {
+ const collaboratorResponse = await github.rest.repos.checkCollaborator({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ username: username
+ });
+
+ if (collaboratorResponse.status === 204) {
+ console.log('Contributor');
+ label = 'Prio Higher';
+ }
+ } catch (error) {
+ console.log('Not a contributor');
+ }
+ }
+
+ if (label !== '') {
+ await github.rest.issues.addLabels({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: issueOrPrNumber,
+ labels: [label]
+ });
+ }
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
index d2150d13f..e36259daa 100644
--- a/.github/workflows/pre-commit.yml
+++ b/.github/workflows/pre-commit.yml
@@ -1,6 +1,7 @@
name: pre-commit
on:
+ workflow_dispatch:
push:
pull_request:
branches: [ master ]
@@ -14,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Setup Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: '3.x'
@@ -24,17 +25,16 @@ jobs:
ruby-version: '3.0'
- name: Checkout TinyUSB
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- - name: Run codespell
- uses: codespell-project/actions-codespell@master
-
- - name: Run Unit Tests
+ - name: Get Dependencies
run: |
- # Install Ceedling
gem install ceedling
- cd test/unit-test
- ceedling test:all
+ #cd test/unit-test
+ #ceedling test:all
+
+ - name: Run pre-commit
+ uses: pre-commit/action@v3.0.0
- name: Build Fuzzer
run: |
diff --git a/.github/workflows/trigger.yml b/.github/workflows/trigger.yml
index e434ca238..cf40ac955 100644
--- a/.github/workflows/trigger.yml
+++ b/.github/workflows/trigger.yml
@@ -1,6 +1,7 @@
name: Trigger Repos
on:
+ workflow_dispatch:
push:
branches: master
release:
@@ -22,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Push to tinyusb_src
run: |
@@ -43,7 +44,7 @@ jobs:
if [ -n "$(git status --porcelain)" ]; then
git add .
git commit --message "Update from https://github.com/$GITHUB_REPOSITORY/commit/$GITHUB_SHA"
- git push
+ git push
fi
- name: Create tinyusb_src Release
@@ -53,8 +54,7 @@ jobs:
cd tinyusb_src
git tag ${{ github.event.release.tag_name }}
git push origin ${{ github.event.release.tag_name }}
-
+
# Send POST reqwuest to release https://docs.github.com/en/rest/reference/repos#create-a-release
- bb={{ github.event.release.body }}
- bb=${bb//\n/\\\n}
+ bb="For release note, please checkout https://github.com/hathach/tinyusb/releases/tag/${{ github.event.release.tag_name }}"
curl -X POST -H "Authorization: token ${{ secrets.API_TOKEN_GITHUB }}" -H "Accept: application/vnd.github.v3+json" --data '{"tag_name": "${{ github.event.release.tag_name }}", "name": "${{ github.event.release.name }}", "body": "$bb", "draft": ${{ github.event.release.draft }}, "prerelease": ${{ github.event.release.prerelease }}}' https://api.github.com/repos/hathach/tinyusb_src/releases
diff --git a/.gitignore b/.gitignore
index 87a5faa80..e6ccec736 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,7 +12,7 @@ latex
*.ind
.env
.settings/
-.idea/
+.vscode/
.gdb_history
/examples/*/*/build*
test_old/
@@ -21,10 +21,69 @@ _build
/examples/*/*/ses
/examples/*/*/ozone
/examples/obsolete
+hw/bsp/**/cubemx/*/
+.mxproject
# coverity intermediate files
cov-int
# cppcheck build directories
*-build-dir
/_bin/
__pycache__
+cmake-build-*
+sdkconfig
+# submodules
+hw/mcu/allwinner
+hw/mcu/bridgetek/ft9xx/ft90x-sdk
+hw/mcu/broadcom
+hw/mcu/gd/nuclei-sdk
+hw/mcu/infineon/mtb-xmclib-cat3
+hw/mcu/microchip
+hw/mcu/mindmotion/mm32sdk
+hw/mcu/nordic/nrfx
+hw/mcu/nuvoton
+hw/mcu/nxp/lpcopen
+hw/mcu/nxp/mcux-sdk
+hw/mcu/nxp/nxp_sdk
+hw/mcu/raspberry_pi/Pico-PIO-USB
+hw/mcu/renesas/rx
+hw/mcu/silabs/cmsis-dfp-efm32gg12b
+hw/mcu/sony/cxd56/spresense-exported-sdk
+hw/mcu/st/cmsis_device_f0
+hw/mcu/st/cmsis_device_f1
+hw/mcu/st/cmsis_device_f2
+hw/mcu/st/cmsis_device_f3
+hw/mcu/st/cmsis_device_f4
+hw/mcu/st/cmsis_device_f7
+hw/mcu/st/cmsis_device_g0
+hw/mcu/st/cmsis_device_g4
+hw/mcu/st/cmsis_device_h7
+hw/mcu/st/cmsis_device_l0
+hw/mcu/st/cmsis_device_l1
+hw/mcu/st/cmsis_device_l4
+hw/mcu/st/cmsis_device_l5
+hw/mcu/st/cmsis_device_u5
+hw/mcu/st/cmsis_device_wb
+hw/mcu/st/stm32f0xx_hal_driver
+hw/mcu/st/stm32f1xx_hal_driver
+hw/mcu/st/stm32f2xx_hal_driver
+hw/mcu/st/stm32f3xx_hal_driver
+hw/mcu/st/stm32f4xx_hal_driver
+hw/mcu/st/stm32f7xx_hal_driver
+hw/mcu/st/stm32g0xx_hal_driver
+hw/mcu/st/stm32g4xx_hal_driver
+hw/mcu/st/stm32h7xx_hal_driver
+hw/mcu/st/stm32l0xx_hal_driver
+hw/mcu/st/stm32l1xx_hal_driver
+hw/mcu/st/stm32l4xx_hal_driver
+hw/mcu/st/stm32l5xx_hal_driver
+hw/mcu/st/stm32u5xx_hal_driver
+hw/mcu/st/stm32wbxx_hal_driver
+hw/mcu/ti
+hw/mcu/wch/ch32v307
+hw/mcu/wch/ch32f20x
+lib/CMSIS_5
+lib/FreeRTOS-Kernel
+lib/lwip
+lib/sct_neopixel
+tools/uf2
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 14f47746b..000000000
--- a/.gitmodules
+++ /dev/null
@@ -1,160 +0,0 @@
-[submodule "hw/mcu/nordic/nrfx"]
- path = hw/mcu/nordic/nrfx
- url = https://github.com/NordicSemiconductor/nrfx.git
-[submodule "tools/uf2"]
- path = tools/uf2
- url = https://github.com/microsoft/uf2.git
-[submodule "hw/mcu/sony/cxd56/spresense-exported-sdk"]
- path = hw/mcu/sony/cxd56/spresense-exported-sdk
- url = https://github.com/sonydevworld/spresense-exported-sdk.git
-[submodule "hw/mcu/ti"]
- path = hw/mcu/ti
- url = https://github.com/hathach/ti_driver.git
-[submodule "hw/mcu/microchip"]
- path = hw/mcu/microchip
- url = https://github.com/hathach/microchip_driver.git
-[submodule "hw/mcu/nuvoton"]
- path = hw/mcu/nuvoton
- url = https://github.com/majbthrd/nuc_driver.git
-[submodule "lib/lwip"]
- path = lib/lwip
- url = https://github.com/lwip-tcpip/lwip.git
-[submodule "hw/mcu/st/cmsis_device_f4"]
- path = hw/mcu/st/cmsis_device_f4
- url = https://github.com/STMicroelectronics/cmsis_device_f4.git
-[submodule "hw/mcu/st/stm32f4xx_hal_driver"]
- path = hw/mcu/st/stm32f4xx_hal_driver
- url = https://github.com/STMicroelectronics/stm32f4xx_hal_driver.git
-[submodule "hw/mcu/st/cmsis_device_f0"]
- path = hw/mcu/st/cmsis_device_f0
- url = https://github.com/STMicroelectronics/cmsis_device_f0.git
-[submodule "hw/mcu/st/stm32f0xx_hal_driver"]
- path = hw/mcu/st/stm32f0xx_hal_driver
- url = https://github.com/STMicroelectronics/stm32f0xx_hal_driver.git
-[submodule "hw/mcu/st/cmsis_device_f1"]
- path = hw/mcu/st/cmsis_device_f1
- url = https://github.com/STMicroelectronics/cmsis_device_f1.git
-[submodule "hw/mcu/st/stm32f1xx_hal_driver"]
- path = hw/mcu/st/stm32f1xx_hal_driver
- url = https://github.com/STMicroelectronics/stm32f1xx_hal_driver.git
-[submodule "hw/mcu/st/cmsis_device_f2"]
- path = hw/mcu/st/cmsis_device_f2
- url = https://github.com/STMicroelectronics/cmsis_device_f2.git
-[submodule "hw/mcu/st/stm32f2xx_hal_driver"]
- path = hw/mcu/st/stm32f2xx_hal_driver
- url = https://github.com/STMicroelectronics/stm32f2xx_hal_driver.git
-[submodule "hw/mcu/st/cmsis_device_f3"]
- path = hw/mcu/st/cmsis_device_f3
- url = https://github.com/STMicroelectronics/cmsis_device_f3.git
-[submodule "hw/mcu/st/stm32f3xx_hal_driver"]
- path = hw/mcu/st/stm32f3xx_hal_driver
- url = https://github.com/STMicroelectronics/stm32f3xx_hal_driver.git
-[submodule "hw/mcu/st/cmsis_device_f7"]
- path = hw/mcu/st/cmsis_device_f7
- url = https://github.com/STMicroelectronics/cmsis_device_f7.git
-[submodule "hw/mcu/st/stm32f7xx_hal_driver"]
- path = hw/mcu/st/stm32f7xx_hal_driver
- url = https://github.com/STMicroelectronics/stm32f7xx_hal_driver.git
-[submodule "hw/mcu/st/cmsis_device_h7"]
- path = hw/mcu/st/cmsis_device_h7
- url = https://github.com/STMicroelectronics/cmsis_device_h7.git
-[submodule "hw/mcu/st/stm32h7xx_hal_driver"]
- path = hw/mcu/st/stm32h7xx_hal_driver
- url = https://github.com/STMicroelectronics/stm32h7xx_hal_driver.git
-[submodule "hw/mcu/st/cmsis_device_l0"]
- path = hw/mcu/st/cmsis_device_l0
- url = https://github.com/STMicroelectronics/cmsis_device_l0.git
-[submodule "hw/mcu/st/stm32l0xx_hal_driver"]
- path = hw/mcu/st/stm32l0xx_hal_driver
- url = https://github.com/STMicroelectronics/stm32l0xx_hal_driver.git
-[submodule "hw/mcu/st/cmsis_device_l1"]
- path = hw/mcu/st/cmsis_device_l1
- url = https://github.com/STMicroelectronics/cmsis_device_l1.git
-[submodule "hw/mcu/st/stm32l1xx_hal_driver"]
- path = hw/mcu/st/stm32l1xx_hal_driver
- url = https://github.com/STMicroelectronics/stm32l1xx_hal_driver.git
-[submodule "hw/mcu/st/cmsis_device_l4"]
- path = hw/mcu/st/cmsis_device_l4
- url = https://github.com/STMicroelectronics/cmsis_device_l4.git
-[submodule "hw/mcu/st/stm32l4xx_hal_driver"]
- path = hw/mcu/st/stm32l4xx_hal_driver
- url = https://github.com/STMicroelectronics/stm32l4xx_hal_driver.git
-[submodule "hw/mcu/st/cmsis_device_g0"]
- path = hw/mcu/st/cmsis_device_g0
- url = https://github.com/STMicroelectronics/cmsis_device_g0.git
-[submodule "hw/mcu/st/stm32g0xx_hal_driver"]
- path = hw/mcu/st/stm32g0xx_hal_driver
- url = https://github.com/STMicroelectronics/stm32g0xx_hal_driver.git
-[submodule "hw/mcu/st/cmsis_device_g4"]
- path = hw/mcu/st/cmsis_device_g4
- url = https://github.com/STMicroelectronics/cmsis_device_g4.git
-[submodule "hw/mcu/st/stm32g4xx_hal_driver"]
- path = hw/mcu/st/stm32g4xx_hal_driver
- url = https://github.com/STMicroelectronics/stm32g4xx_hal_driver.git
-[submodule "hw/mcu/st/cmsis_device_l5"]
- path = hw/mcu/st/cmsis_device_l5
- url = https://github.com/STMicroelectronics/cmsis_device_l5.git
-[submodule "hw/mcu/st/stm32l5xx_hal_driver"]
- path = hw/mcu/st/stm32l5xx_hal_driver
- url = https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git
-[submodule "hw/mcu/st/cmsis_device_wb"]
- path = hw/mcu/st/cmsis_device_wb
- url = https://github.com/STMicroelectronics/cmsis_device_wb.git
-[submodule "hw/mcu/st/stm32wbxx_hal_driver"]
- path = hw/mcu/st/stm32wbxx_hal_driver
- url = https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git
-[submodule "lib/sct_neopixel"]
- path = lib/sct_neopixel
- url = https://github.com/gsteiert/sct_neopixel
-[submodule "lib/FreeRTOS-Kernel"]
- path = lib/FreeRTOS-Kernel
- url = https://github.com/FreeRTOS/FreeRTOS-Kernel.git
-[submodule "lib/CMSIS_5"]
- path = lib/CMSIS_5
- url = https://github.com/ARM-software/CMSIS_5.git
-[submodule "hw/mcu/silabs/cmsis-dfp-efm32gg12b"]
- path = hw/mcu/silabs/cmsis-dfp-efm32gg12b
- url = https://github.com/cmsis-packs/cmsis-dfp-efm32gg12b
-[submodule "hw/mcu/renesas/rx"]
- path = hw/mcu/renesas/rx
- url = https://github.com/kkitayam/rx_device.git
-[submodule "hw/mcu/nxp/lpcopen"]
- path = hw/mcu/nxp/lpcopen
- url = https://github.com/hathach/nxp_lpcopen.git
-[submodule "hw/mcu/nxp/mcux-sdk"]
- path = hw/mcu/nxp/mcux-sdk
- url = https://github.com/NXPmicro/mcux-sdk.git
-[submodule "hw/mcu/nxp/nxp_sdk"]
- path = hw/mcu/nxp/nxp_sdk
- url = https://github.com/hathach/nxp_sdk.git
-[submodule "hw/mcu/gd/nuclei-sdk"]
- path = hw/mcu/gd/nuclei-sdk
- url = https://github.com/Nuclei-Software/nuclei-sdk.git
-[submodule "hw/mcu/bridgetek/ft9xx/ft90x-sdk"]
- path = hw/mcu/bridgetek/ft9xx/ft90x-sdk
- url = https://github.com/BRTSG-FOSS/ft90x-sdk
-[submodule "hw/mcu/mindmotion/mm32sdk"]
- path = hw/mcu/mindmotion/mm32sdk
- url = https://github.com/hathach/mm32sdk.git
-[submodule "hw/mcu/broadcom"]
- path = hw/mcu/broadcom
- url = https://github.com/adafruit/broadcom-peripherals.git
- branch = main-build
-[submodule "hw/mcu/infineon/mtb-xmclib-cat3"]
- path = hw/mcu/infineon/mtb-xmclib-cat3
- url = https://github.com/Infineon/mtb-xmclib-cat3.git
-[submodule "hw/mcu/allwinner"]
- path = hw/mcu/allwinner
- url = https://github.com/hathach/allwinner_driver.git
-[submodule "hw/mcu/wch/ch32v307"]
- path = hw/mcu/wch/ch32v307
- url = https://github.com/openwch/ch32v307.git
-[submodule "hw/mcu/raspberry_pi/Pico-PIO-USB"]
- path = hw/mcu/raspberry_pi/Pico-PIO-USB
- url = https://github.com/sekigon-gonnoc/Pico-PIO-USB.git
-[submodule "hw/mcu/st/cmsis_device_u5"]
- path = hw/mcu/st/cmsis_device_u5
- url = https://github.com/STMicroelectronics/cmsis_device_u5
-[submodule "hw/mcu/st/stm32u5xx_hal_driver"]
- path = hw/mcu/st/stm32u5xx_hal_driver
- url = https://github.com/STMicroelectronics/stm32u5xx_hal_driver
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 000000000..b0811f163
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,10 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# GitHub Copilot persisted chat sessions
+/copilot/chatSessions
diff --git a/.idea/cmake.xml b/.idea/cmake.xml
new file mode 100644
index 000000000..22199b103
--- /dev/null
+++ b/.idea/cmake.xml
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/kl25.xml b/.idea/runConfigurations/kl25.xml
new file mode 100644
index 000000000..96c208dde
--- /dev/null
+++ b/.idea/runConfigurations/kl25.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/lpc1857.xml b/.idea/runConfigurations/lpc1857.xml
new file mode 100644
index 000000000..a4764b9d6
--- /dev/null
+++ b/.idea/runConfigurations/lpc1857.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/lpc4088.xml b/.idea/runConfigurations/lpc4088.xml
new file mode 100644
index 000000000..9da975ef3
--- /dev/null
+++ b/.idea/runConfigurations/lpc4088.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/lpc54628.xml b/.idea/runConfigurations/lpc54628.xml
new file mode 100644
index 000000000..0c3877e94
--- /dev/null
+++ b/.idea/runConfigurations/lpc54628.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/lpc55s69.xml b/.idea/runConfigurations/lpc55s69.xml
new file mode 100644
index 000000000..2fa127d33
--- /dev/null
+++ b/.idea/runConfigurations/lpc55s69.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/mcx947.xml b/.idea/runConfigurations/mcx947.xml
new file mode 100644
index 000000000..12180a996
--- /dev/null
+++ b/.idea/runConfigurations/mcx947.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/nrf52840.xml b/.idea/runConfigurations/nrf52840.xml
new file mode 100644
index 000000000..8e48a2b97
--- /dev/null
+++ b/.idea/runConfigurations/nrf52840.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/nrf5340.xml b/.idea/runConfigurations/nrf5340.xml
new file mode 100644
index 000000000..646f2d38c
--- /dev/null
+++ b/.idea/runConfigurations/nrf5340.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/ra4m1.xml b/.idea/runConfigurations/ra4m1.xml
new file mode 100644
index 000000000..72bc63d9b
--- /dev/null
+++ b/.idea/runConfigurations/ra4m1.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/ra6m1.xml b/.idea/runConfigurations/ra6m1.xml
new file mode 100644
index 000000000..ca8c7245a
--- /dev/null
+++ b/.idea/runConfigurations/ra6m1.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/ra6m5.xml b/.idea/runConfigurations/ra6m5.xml
new file mode 100644
index 000000000..ecbdb21b7
--- /dev/null
+++ b/.idea/runConfigurations/ra6m5.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/rp2040.xml b/.idea/runConfigurations/rp2040.xml
new file mode 100644
index 000000000..51ab7b5cc
--- /dev/null
+++ b/.idea/runConfigurations/rp2040.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/rt1010.xml b/.idea/runConfigurations/rt1010.xml
new file mode 100644
index 000000000..f415c0676
--- /dev/null
+++ b/.idea/runConfigurations/rt1010.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/rt1060.xml b/.idea/runConfigurations/rt1060.xml
new file mode 100644
index 000000000..cc75aa62c
--- /dev/null
+++ b/.idea/runConfigurations/rt1060.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/samd21g18.xml b/.idea/runConfigurations/samd21g18.xml
new file mode 100644
index 000000000..f8aa6009d
--- /dev/null
+++ b/.idea/runConfigurations/samd21g18.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/samd51j19.xml b/.idea/runConfigurations/samd51j19.xml
new file mode 100644
index 000000000..694ea7dfd
--- /dev/null
+++ b/.idea/runConfigurations/samd51j19.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/stlink.xml b/.idea/runConfigurations/stlink.xml
new file mode 100644
index 000000000..628f7910d
--- /dev/null
+++ b/.idea/runConfigurations/stlink.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/stm32g474.xml b/.idea/runConfigurations/stm32g474.xml
new file mode 100644
index 000000000..6d65e83c7
--- /dev/null
+++ b/.idea/runConfigurations/stm32g474.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/stm32h743.xml b/.idea/runConfigurations/stm32h743.xml
new file mode 100644
index 000000000..aeaf9fb53
--- /dev/null
+++ b/.idea/runConfigurations/stm32h743.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/uno_r4.xml b/.idea/runConfigurations/uno_r4.xml
new file mode 100644
index 000000000..98bf91812
--- /dev/null
+++ b/.idea/runConfigurations/uno_r4.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 000000000..94a25f7f4
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 000000000..bba217cc9
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,44 @@
+# SPDX-FileCopyrightText: 2020 Diego Elio PettenÃ˛
+#
+# SPDX-License-Identifier: Unlicense
+
+repos:
+- repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.4.0
+ hooks:
+ - id: check-yaml
+ - id: trailing-whitespace
+ exclude: |
+ (?x)^(
+ hw/bsp/mcx/sdk/
+ )
+ - id: end-of-file-fixer
+ exclude: |
+ (?x)^(
+ .idea/|
+ hw/bsp/mcx/sdk/|
+ docs/contributing/code_of_conduct.rst|
+ docs/info/contributors.rst
+ )
+ - id: forbid-submodules
+
+- repo: https://github.com/codespell-project/codespell
+ rev: v2.2.4
+ hooks:
+ - id: codespell
+ args: [-w]
+ exclude: |
+ (?x)^(
+ lib/|
+ hw/bsp/mcx/sdk/
+ )
+
+- repo: local
+ hooks:
+ - id: unit-test
+ name: unit-test
+ files: ^(src/|test/unit-test/)
+ entry: sh -c "cd test/unit-test && ceedling test:all"
+ pass_filenames: false
+ types_or: [c, header]
+ language: system
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index e83cd90fd..e26b1f475 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -4,15 +4,21 @@
version: 2
+# Set the version of Python and other tools you might need
+build:
+ os: ubuntu-22.04
+ tools:
+ python: "3.11"
+
+# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py
+# Optionally declare the Python requirements required to build your docs
python:
- version: 3.8
install:
- requirements: docs/requirements.txt
submodules:
include: []
recursive: false
-
\ No newline at end of file
diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst
index 5726169f8..085f8082a 100644
--- a/CONTRIBUTORS.rst
+++ b/CONTRIBUTORS.rst
@@ -119,6 +119,7 @@ Notable contributors
- Port DCD Synopsys to support Silabs EFM32GG12 with SLTB009A board
- Rewrite documentation in rst and setup for readthedocs
+- Generalize Renesas driver and support RA family with EK-RA4M3 board
`Raspberry Pi Team `__
@@ -199,6 +200,8 @@ Notable contributors
- Add new DCD port for Microchip SAMx7x
- Add IAR compiler support
- Improve UAC2, CDC, DFU class driver
+- Improve stm32_fsdev, chipidea_ci_hs, lpc_ip3511 DCD
+- Host IAR Build CI & hardware in the loop (HITL) test
`Full contributors list `__
diff --git a/README.rst b/README.rst
index 7825a1b0a..8c3145d33 100644
--- a/README.rst
+++ b/README.rst
@@ -1,14 +1,24 @@
+|Build Status| |Documentation Status| |Fuzzing Status| |License|
+
+Sponsors
+========
+
+TinyUSB is funded by: Adafruit. Purchasing products from them helps to support this project.
+
+.. figure:: docs/assets/adafruit_logo.svg
+ :alt: Adafruit Logo
+ :target: https://www.adafruit.com
+
+TinyUSB Project
+===============
+
.. figure:: docs/assets/logo.svg
:alt: TinyUSB
-|Build Status| |Documentation Status| |Fuzzing Status| |License|
-
TinyUSB is an open-source cross-platform USB Host/Device stack for
embedded system, designed to be memory-safe with no dynamic allocation
and thread-safe with all interrupt events are deferred then handled in
-the non-ISR task function.
-
-Please take a look at the online `documentation `__.
+the non-ISR task function. Check out the online `documentation `__ for more details.
.. figure:: docs/assets/stack.svg
:width: 500px
@@ -16,47 +26,30 @@ Please take a look at the online `documentation `__.
::
- .
- âââ docs # Documentation
- âââ examples # Sample with Makefile build support
- âââ hw
- â  âââ bsp # Supported boards source files
- â  âââ mcu # Low level mcu core & peripheral drivers
- âââ lib # Sources from 3rd party such as freeRTOS, fatfs ...
- âââ src # All sources files for TinyUSB stack itself.
- âââ test # Unit tests for the stack
- âââ tools # Files used internally
+ .
+ âââ docs # Documentation
+ âââ examples # Examples with make and cmake build system
+ âââ hw
+ â âââ bsp # Supported boards source files
+ â âââ mcu # Low level mcu core & peripheral drivers
+ âââ lib # Sources from 3rd party such as freeRTOS, fatfs ...
+ âââ src # All sources files for TinyUSB stack itself.
+ âââ test # Tests: unit test, fuzzing, hardware test
+ âââ tools # Files used internally
-Supported MCUs
-==============
-The stack supports the following MCUs:
+Getting started
+===============
-- **Allwinner:** F1C100s/F1C200s
-- **Broadcom:** BCM2837, BCM2711
-- **Dialog:** DA1469x
-- **Espressif:** ESP32-S2, ESP32-S3
-- **GigaDevice:** GD32VF103
-- **Infineon:** XMC4500
-- **MicroChip:** SAMD11, SAMD21, SAMD51, SAME5x, SAMG55, SAML21, SAML22, SAME7x
-- **NordicSemi:** nRF52833, nRF52840, nRF5340
-- **Nuvoton:** NUC120, NUC121/NUC125, NUC126, NUC505
-- **NXP:**
+See the `online documentation `_ for information about using TinyUSB and how it is implemented.
- - iMX RT Series: RT10xx, RT11xx
- - Kinetis: KL25, K32L2
- - LPC Series: 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55
+We use `GitHub Discussions `_ as our forum. It is a great place to ask questions and advice from the community or to discuss your TinyUSB-based projects.
-- **Raspberry Pi:** RP2040
-- **Renesas:** RX63N, RX65N, RX72N
-- **Silabs:** EFM32GG
-- **Sony:** CXD56
-- **ST:** STM32 series: F0, F1, F2, F3, F4, F7, H7, G4, L0, L1, L4, L4+, WB
-- **TI:** MSP430, MSP432E4, TM4C123
-- **ValentyUSB:** eptri
-- **WCH:** CH32V307
+For bugs and feature requests, please `raise an issue `_ and follow the templates there.
-Here is the list of `Supported Devices`_ that can be used with provided examples.
+Check out `Getting Started`_ guide for adding TinyUSB to your project or building the examples. If you are new to TinyUSB, we recommend starting with the `cdc_msc` example.
+
+See `Porting`_ guide for adding support for new MCUs and boards.
Device Stack
============
@@ -83,8 +76,19 @@ Host Stack
- Human Interface Device (HID): Keyboard, Mouse, Generic
- Mass Storage Class (MSC)
+- Communication Device Class: CDC-ACM
+- Vendor serial over USB: FTDI, CP210x
- Hub with multiple-level support
+Similar to the Device Stack, if you have a special requirement, `usbh_app_driver_get_cb()` can be used to write your own class driver without modifying the stack.
+
+TypeC PD Stack
+==============
+
+- Power Delivery 3.0 (PD3.0) with USB Type-C support (WIP)
+- Super early stage, only for testing purpose
+- Only support STM32 G4
+
OS Abstraction layer
====================
@@ -95,6 +99,76 @@ TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR)
- `RT-Thread `_: `repo `_
- **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its `own repo `_
+Supported CPUs
+==============
+
+Following CPUs are supported, check out `Supported Devices`_ for comprehensive list of driver, features for each CPU.
+
++--------------+------------------------------------------------------------+
+| Manufacturer | Family |
++==============+============================================================+
+| Allwinner | F1C100s/F1C200s |
++--------------+------------------------------------------------------------+
+| Analog | MAX3421E (usb host shield) |
++--------------+------------------------------------------------------------+
+| Brigetek | FT90x |
++--------------+------------------------------------------------------------+
+| Broadcom | BCM2711, BCM2837 |
++--------------+------------------------------------------------------------+
+| Dialog | DA1469x |
++--------------+------------------------------------------------------------+
+| Espressif | ESP32 S2, S3 |
++--------------+------------------------------------------------------------+
+| GigaDevice | GD32VF103 |
++--------------+------------------------------------------------------------+
+| Infineon | XMC4500 |
++--------------+-----+------------------------------------------------------+
+| MicroChip | SAM | D11, D21, D51, E5x, G55, L2x, E7x, S7x, V7x |
+| +-----+------------------------------------------------------+
+| | PIC | 24, 32mm, 32mk, 32mx, 32mz, dsPIC33 |
++--------------+-----+------------------------------------------------------+
+| Mind Montion | mm32 |
++--------------+------------------------------------------------------------+
+| NordicSemi | nRF52833, nRF52840, nRF5340 |
++--------------+------------------------------------------------------------+
+| Nuvoton | NUC 120, 121, 125, 126, 505 |
++--------------+---------+--------------------------------------------------+
+| NXP | iMXRT | RT10xx, RT11xx |
+| +---------+--------------------------------------------------+
+| | Kinetis | KL, K32L2 |
+| +---------+--------------------------------------------------+
+| | LPC | 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55 |
+| +---------+--------------------------------------------------+
+| | MCX | A15, N9 |
++--------------+---------+--------------------------------------------------+
+| Raspberry Pi | RP2040 |
++--------------+-----+------------------------------------------------------+
+| Renesas | RX | 63N, 65N, 72N |
++--------------+-----+------------------------------------------------------+
+| | RA | 4M1, 4M3, 6M1, 6M5 |
++--------------+-----+------------------------------------------------------+
+| Silabs | EFM32GG12 |
++--------------+------------------------------------------------------------+
+| Sony | CXD56 |
++--------------+------------------------------------------------------------+
+| ST STM32 | F0, F1, F2, F3, F4, F7, H7, G0, G4, L0, L1, L4, L4+ U5, WB |
++--------------+------------------------------------------------------------+
+| TI | MSP430, MSP432E4, TM4C123 |
++--------------+------------------------------------------------------------+
+| ValentyUSB | eptri |
++--------------+------------------------------------------------------------+
+| WCH | CH32F20x, CH32V307, |
++--------------+------------------------------------------------------------+
+
+License
+=======
+
+All TinyUSB sources in the ``src`` folder are licensed under MIT
+license, the `Full license is here `__. However, each file can be
+individually licensed especially those in ``lib`` and ``hw/mcu`` folder.
+Please make sure you understand all the license term for files you use
+in your project.
+
Docs
====
@@ -108,6 +182,7 @@ Docs
- `Supported Devices`_
- `Getting Started`_
+ - `Dependencies`_
- `Concurrency`_
- `Contributing`_
@@ -116,17 +191,7 @@ Docs
- `Structure`_
- `Porting`_
-License
-=======
-
-All TinyUSB sources in the ``src`` folder are licensed under MIT
-license, the `Full license is here `__. However, each file can be
-individually licensed especially those in ``lib`` and ``hw/mcu`` folder.
-Please make sure you understand all the license term for files you use
-in your project.
-
-
-.. |Build Status| image:: https://github.com/hathach/tinyusb/workflows/Build/badge.svg
+.. |Build Status| image:: https://github.com/hathach/tinyusb/actions/workflows/cmake_arm.yml/badge.svg
:target: https://github.com/hathach/tinyusb/actions
.. |Documentation Status| image:: https://readthedocs.org/projects/tinyusb/badge/?version=latest
:target: https://docs.tinyusb.org/en/latest/?badge=latest
@@ -142,6 +207,7 @@ in your project.
.. _Reference: docs/reference/index.rst
.. _Supported Devices: docs/reference/supported.rst
.. _Getting Started: docs/reference/getting_started.rst
+.. _Dependencies: docs/reference/dependencies.rst
.. _Concurrency: docs/reference/concurrency.rst
.. _Contributing: docs/contributing/index.rst
.. _Code of Conduct: CODE_OF_CONDUCT.rst
diff --git a/SConscript b/SConscript
new file mode 100644
index 000000000..b5043f437
--- /dev/null
+++ b/SConscript
@@ -0,0 +1,11 @@
+# RT-Thread building script for bridge
+
+import os
+from building import *
+
+objs = []
+cwd = GetCurrentDir()
+
+objs = objs + SConscript(cwd + '/lib/rt-thread/SConscript')
+
+Return('objs')
diff --git a/docs/assets/adafruit_logo.svg b/docs/assets/adafruit_logo.svg
new file mode 100644
index 000000000..cafd5a10e
--- /dev/null
+++ b/docs/assets/adafruit_logo.svg
@@ -0,0 +1,21 @@
+
diff --git a/docs/assets/stack.svg b/docs/assets/stack.svg
index 85fe35e96..ed46c8649 100644
--- a/docs/assets/stack.svg
+++ b/docs/assets/stack.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/docs/contributing/porting.rst b/docs/contributing/porting.rst
index 710af51c3..f81d98782 100644
--- a/docs/contributing/porting.rst
+++ b/docs/contributing/porting.rst
@@ -62,9 +62,9 @@ Feel free to skip this until you want to verify your demo code is running. To im
OS Abstraction Layer (OSAL)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The OS Abstraction Layer is responsible for providing basic data structures for TinyUSB that may allow for concurrency when used with an RTOS. Without an RTOS it simply handles concurrency issues between the main code and interrupts.
+The OS Abstraction Layer is responsible for providing basic data structures for TinyUSB that may allow for concurrency when used with an RTOS. Without an RTOS it simply handles concurrency issues between the main code and interrupts. The code is almost entirely agnostic of MCU and lives in ``src/osal``.
-The code is almost entirely agnostic of MCU and lives in ``src/osal``.
+In RTOS configurations, tud_task()/tuh_task() blocks behind a synchronization structure when the event queue is empty, so that the scheduler may give the CPU to a different task. To take advantage of the library's capability to yield the CPU when there are no actionable USB device events, ensure that the `CFG_TUSB_OS` symbol is defined, e.g `OPT_OS_FREERTOS` enables the FreeRTOS scheduler to schedule other threads than that which calls `tud_task()/tuh_task()`.
Device API
^^^^^^^^^^
diff --git a/docs/info/changelog.rst b/docs/info/changelog.rst
index 451e3dace..b359ebb44 100644
--- a/docs/info/changelog.rst
+++ b/docs/info/changelog.rst
@@ -2,6 +2,148 @@
Changelog
*********
+0.16.0
+======
+
+- New controller driver: MAX3421e (usb host shield), rusb2 (Renesas USB2.0), ChipIdea fullspeed
+- New MCUs: MCXn9, nRF5340, STM32: G0, G4, L5, U575, U5A5, RA6m5, CH32F20x
+- Add initial TypeC PowerDelivery support with STM32G4
+- Remove submodules and use python script to manage repo dependencies #1947
+- Add CMake support for most families and boards, move build file from tools/ to examples/build_system
+- Add ETM trace support with JTrace for nrf52840, nrf5340, mcb1857, stm32h743eval, ra6m5
+- [osal] Make it possible to override the osal_task_delay() in osal_none
+- Add CDC+UAC2 composite device example
+- Enhance Hardware-in-the-loop (HIL) testing with more boards: rp2040, stm32l412nucleo, stm32f746disco, lpcxpresso43s67
+
+Controller Driver (DCD & HCD)
+-----------------------------
+
+- Add new ISO endpoint API: dcd_edpt_iso_alloc() and dcd_edpt_iso_activate()
+- Remove legacy driver st/synopsys
+
+- EHCI
+
+ - [iMXRT] Add dache clean/invalidate when memory is in cacheable memory
+ - Fix portsc write issue which cause problem with enumeration
+ - Fix an issue when doing port reset write to portsc
+ - Fix port change detect is not recognized when power on with attached device
+ - Fix xfer failed with disconnected device as stalled
+ - Fix error on EHCI causes xfer error in non-queued qhd which cause memory fault
+ - Un-roll recursive hub removal with usbh queue
+ - Fix issue when removing queue head
+ - Implement hcd_edpt_abort_xfer()
+ - use standard USB complete interrupt instead of custom chipidea async/period interrupt to be more compatible with other ehci implementation
+ - refactor usb complete & error isr processing, merge, update. Fix EHCI QHD reuses QTD on wrong endpoint
+ - Improve bus reset, fix send_setup() not carried out if halted previously
+ - Fix clear qhd halted bit if not caused by STALL protocol to allow for next transfer
+
+- ChipIdea Highspeed
+
+ - Fix control transfer issue when previous status and new setup complete in the same isr frame
+ - [imxrt] Add dcache support for cache region
+
+- ChipIdea Fullspeed
+
+ - Generalize ChipIdea Fullspeed driver for mcxn9 (port 0), kinetis
+
+- nrf
+
+ - Fix DMA race condition with ISO OUT transfer #1946
+ - Add support for nRF5340 with pca10095 board
+
+- Renesas rusb2
+
+ - Generalize rusb2 driver for ra, rx mcus
+ - rework both dcd and hcd for better multiple ports support
+ - Add support for board with HS USB port: ra6m5 port1
+
+- rp2040
+
+ - [dcd] Make writes to SIE_CTRL aware of concurrent access
+ - [hcd] add hcd_frame_number(), hcd_edpt_abort_xfer() for pio-usb host
+
+- stm32 fsdev:
+
+ - Add STM32L5 support
+ - Implement dcd_edpt_iso_alloc() and dcd_edpt_iso_activate()
+
+- OHCI
+
+ - Allows configurable root hub ports, handles SMM mode (Ref OHCI spec 5.1.1.3.3) and Bios mode (Ref OHCI spec 5.1.1.3.4)
+ - Fix FrameIntervalToggle must be toggled after we write the FrameInterval (Ref OHCI Spec 7.3.1)
+ - Wait PowerOnToPowerGoodTime after we enable power of the RH ports (Ref OHCI Spec 7.4.1)
+ - Generate port interrupts for devices already connected during init.
+ - Fix issue when removing queue head
+ - Disable MIE during IRQ processing and clear HccaDoneHead on completion as per OCHI Spec Page 80
+
+Device Stack
+------------
+
+- Add optional hooks tud_event_hook_cb()
+- Audio (UAC2)
+
+ - Fix feedback EP buffer alignment.
+ - Fix encoding, update example
+ - Improve IN transfer
+
+- Bluetooth
+
+ - Add historical EP compatibility for Bluetooth HCI
+
+- CDC
+
+ - Fix line_coding alignment
+ - Fix typo in cdc line coding enum
+
+- MIDI
+
+ - Fix stream_write() always writes system messages to cable 0
+ - Fix incorrect NOTE_ON, NOTE_OFF definitions
+
+- USBTMC: Fix tmc488 bit order
+
+- Vendor: fix read()/write() race condition
+
+- Video (UVC)
+
+ - Add the capability for video class to handle a bulk endpoint in the streaming interface.
+
+Host Stack
+----------
+
+- USBH
+
+ - Add new APIs: tuh_interface_set(), tuh_task_event_ready(), tuh_edpt_abort_xfer(), tuh_rhport_reset_bus(), tuh_rhport_is_active()
+ - Fix issue when device generate multiple attach/detach/attach when plugging in
+ - Prefer application callback over built-in driver on transfer complete event
+ - Correct hcd_edpt_clear_stall() API signature
+ - Separate bus reset delay and contact debouncing delay in enumeration
+ - Support usbh_app_driver_get_cb() for application drivers
+ - Fix usbh enumeration removal race condition
+ - Add optional hooks tuh_event_hook_cb()
+
+- CDC
+
+ - Breaking: change tuh_cdc_itf_get_info() to use tuh_itf_info_t instead of tuh_cdc_info_t
+ - Fix cdc host enumeration issue when device does not support line request
+ - Add support for vendor usb2uart serial: ftdi, cp210x, ch9102f
+ - Improve sync control API e.g tuh_cdc_set_control_line_state(), tuh_cdc_set_line_coding()
+
+- HID
+
+ - Add new APIs tuh_hid_send_report(), tuh_hid_itf_get_info(), tuh_hid_receive_ready(), tuh_hid_send_ready(), tuh_hid_set_default_protocol()
+ - Change meaning of CFG_TUH_HID to total number of HID interfaces supported. Previously CFG_TUH_HID is max number of interfaces per device which is rather limited and consume more resources than needed.
+
+- HUB
+
+ - Fix handling of empty "status change" interrupt
+ - Fix issue with hub status_change is not aligned
+
+- MSC
+
+ - Fix bug in tuh_msc_ready()
+ - Fix host msc get maxlun not using aligned section memory
+
0.15.0
======
@@ -15,7 +157,7 @@ Changelog
- Fix tu_fifo memory overflown when repeatedly write to overwritable fifo (accumulated more than 2 depths)
- Better support for IAR (ARM) with ci build check for stm32 mcus.
- Fix Windows build for some mingw gnu make situations
-
+
Controller Driver (DCD & HCD)
-----------------------------
@@ -27,7 +169,7 @@ Controller Driver (DCD & HCD)
- Fix endpoint internal state when closed
- Fix reception of large ISO packets
-- [rp2040]
+- [rp2040]
- [dcd] Implement workaround for Errata 15. This enable SOF when bulk-in endpoint is in use and reduce its bandwidth to only 80%
- [hcd] Fix shared irq slots filling up when hcd_init() is called multiple times
@@ -51,7 +193,7 @@ Device Stack
- Support port name strings
- fix MS Header wTotalLength computation
-
+
- [HID]
- Add FIDO descriptor template
@@ -60,7 +202,7 @@ Device Stack
- [CDC]
- Fix autoflush for FIFO < MPS
- - Fix tx fifo memory overflown when DTR is not set and tud_cdc_write() is called repeatedly with large enough data
+ - Fix tx fifo memory overflown when DTR is not set and tud_cdc_write() is called repeatedly with large enough data
- [USBTMC] Fix packet size with highspeed
@@ -93,21 +235,21 @@ Controller Driver (DCD & HCD)
- CFG_TUD_ENABLED/CFG_TUH_ENABLED, CFG_TUD_MAX_SPEED/CFG_TUH_MAX_SPEED can be used to replace CFG_TUSB_RHPORT0_MODE/CFG_TUSB_RHPORT1_MODE
- tud_init(rphort), tuh_init(rhport) can be used to init stack on specified roothub port (controller) instead of tusb_init(void)
-- Add dcd/hcd port specific defines TUP_ (stand for tinyusb port-specific)
+- Add dcd/hcd port specific defines `TUP_` (stand for tinyusb port-specific)
- [dwc2]
- Update to support stm32 h72x, h73x with only 1 otg controller
- Fix overwrite with grstctl when disable endpoint
- [EHCI] Fix an issue with EHCI driver
- [msp430] Fix for possible bug in msp430-elf-gcc 9.3.0
-- [nrf5x] Fix DMA access race condition using atomic function
+- [nrf5x] Fix DMA access race condition using atomic function
- [pic32] Fix PIC32 santiy
- [rp2040]
- Add PICO-PIO-USB as controller (device/host) support for rp2040
- Use shared IRQ handlers, so user can also hook the USB IRQ
- Fix resumed signal not reported to device stack
-- [stm32fsdev] Add support for stm32wb55
+- [stm32fsdev] Add support for stm32wb55
Device Stack
------------
@@ -159,7 +301,7 @@ Controller Driver (DCD & HCD)
- [F1C100s] Add new DCD for Allwinner F1C100s family
- [PIC32MZ] Add new DCD for PIC32MZ
- [nRF] Fix/Enhance various race condition with: EASY DMA, request HFXO, EPOUT
-- [ChipIdea] rename Transdimension to more popular ChipIdea Highspeed,
+- [ChipIdea] rename Transdimension to more popular ChipIdea Highspeed,
- [RP2040] various update/fix for hcd/dcd
- [FT9XX] new DCD port for Bridgetek FT90x and FT93x devices
- [DA1469X] Fix resume
@@ -246,7 +388,7 @@ RP2040
^^^^^^
- Add RP2040 suspend & resume support
-- Implement double buffer for both host and device (#891). However device EPOUT is still single buffered due to techinical issue with short packet
+- Implement double buffer for both host and device (#891). However device EPOUT is still single buffered due to techinical issue with short packet
Device Stack
------------
@@ -267,7 +409,7 @@ DFU
^^^
- Enhance DFU implementation to support multiple alternate interface and better support bwPollTimeout
-- Rename CFG_TUD_DFU_MODE to simply CFG_TUD_DFU
+- Rename CFG_TUD_DFU_MODE to simply CFG_TUD_DFU
HID
^^^
@@ -287,7 +429,7 @@ UAC2
^^^^
- Fix bug and enhance of UAC2
-
+
Vendor
^^^^^^
@@ -479,7 +621,7 @@ Host Controller Driver (HCD)
- Move echi/ohci files to portable/
- Rename hcd_lpc18_43 to hcd_transdimension
- Sub hcd API with hcd_ehci_init(), hcd_ehci_register_addr()
-
+
- Update NXP transdimention hcd_init() to reset controller to host mode
- Ported hcd to rt10xx
@@ -529,13 +671,13 @@ Device Controller Driver
- ESP32-S2:
- Add bus suspend and wakeup support
-
+
- SAMD21:
- Fix (walkaround) samd21 setup_packet overflow by USB DMA
-
+
- STM32 Synopsys:
- Rework USB FIFO allocation scheme and allow RX FIFO size reduction
-
+
- Sony CXD56
- Update Update Spresense SDK to 2.0.2
- Fix dcd issues with setup packets
@@ -554,17 +696,17 @@ USB Device
- CDC
- Allow to transmit data, even if the host does not support control line states i.e set DTR
-
+
- HID
- change default CFG_TUD_HID_EP_BUFSIZE from 16 to 64
-
+
- MIDI
- Fix midi sysex sending bug
-
+
- MSC
- Invoke only scsi complete callback after status transaction is complete.
- Fix scsi_mode_sense6_t padding, which cause IAR compiler internal error.
-
+
- USBTMC
- Change interrupt endpoint example size to 8 instead of 2 for better compatibility with mcu
@@ -614,20 +756,20 @@ Device Controller Driver
- Fix FIFO flush during stall
- Implement dcd_edpt_close() API
- Support F105, F107
-
+
- Enhance STM32 fsdev
- Improve dcd fifo allocation
- Fix ISTR race condition
- Support remap USB IRQ on supported MCUs
- Implement dcd_edpt_close() API
-
+
- Enhance NUC 505: enhance set configure behavior
- Enhance SAMD
- Fix race condition with setup packet
- Add SAMD11 option `OPT_MCU_SAMD11`
- Add SAME5x option `OPT_MCU_SAME5X`
-
+
- Fix SAMG control data toggle and stall race condition
- Enhance nRF
@@ -659,7 +801,7 @@ USB Device
- `usbd_driver_open()` add max length argument, and return length of interface (0 for not supported). Return value is used for finding appropriate driver
- Add application implemented class driver via `usbd_app_driver_get_cb()`
- IAD is handled to assign driver id
-
+
- Added `tud_descriptor_device_qualifier_cb()` callback
- Optimize `tu_fifo` bulk write/read transfer
- Forward non-std control request to class driver
@@ -675,12 +817,12 @@ USB Device
- Send zero length packet for end of data when needed
- Add `tud_cdc_tx_complete_cb()` callback
- Change tud_cdc_n_write_flush() return number of bytes forced to transfer, and flush when writing enough data to fifo
-
+
- MIDI:
- Add packet interface
- Add multiple jack descriptors
- Fix MIDI driver for sysex
-
+
- DFU Runtime: fix response to SET_INTERFACE and DFU_GETSTATUS request
- Rename some configure macro to make it clear that those are used directly for endpoint transfer
@@ -688,7 +830,7 @@ USB Device
- CFG_TUD_CDC_EPSIZE to CFG_TUD_CDC_EP_BUFSIZE
- CFG_TUD_MSC_BUFSIZE to CFG_TUD_MSC_EP_BUFSIZE
- CFG_TUD_MIDI_EPSIZE to CFG_TUD_MIDI_EP_BUFSIZE
-
+
- HID:
- Fix gamepad template descriptor
- Add multiple HID interface API
@@ -700,7 +842,7 @@ USB Host
- Rework USB host stack (still work in progress)
- Fix compile error with pipehandle
- Rework usbh control and enumeration as non-blocking
-
+
- Improve Hub, MSC, HID host driver
Examples
@@ -713,7 +855,7 @@ Examples
- Enhance `net_lwip_webserver` example
- Add multiple configuration: RNDIS for Windows, CDC-ECM for macOS (Linux will work with both)
- Update lwip to STABLE-2_1_2_RELEASE for net_lwip_webserver
-
+
- Added new Audio example: audio_test uac2_headsest
New Boards
diff --git a/docs/reference/dependencies.rst b/docs/reference/dependencies.rst
new file mode 100644
index 000000000..6ba6692e9
--- /dev/null
+++ b/docs/reference/dependencies.rst
@@ -0,0 +1,64 @@
+************
+Dependencies
+************
+
+MCU low-level peripheral driver and external libraries for building TinyUSB examples
+
+======================================== ============================================================== ======================================== =======================================================================================================================================================================================================
+Local Path Repo Commit Required by
+======================================== ============================================================== ======================================== =======================================================================================================================================================================================================
+hw/mcu/allwinner https://github.com/hathach/allwinner_driver.git 8e5e89e8e132c0fd90e72d5422e5d3d68232b756 fc100s
+hw/mcu/bridgetek/ft9xx/ft90x-sdk https://github.com/BRTSG-FOSS/ft90x-sdk.git 91060164afe239fcb394122e8bf9eb24d3194eb1 brtmm90x
+hw/mcu/broadcom https://github.com/adafruit/broadcom-peripherals.git 08370086080759ed54ac1136d62d2ad24c6fa267 broadcom_32bit broadcom_64bit
+hw/mcu/gd/nuclei-sdk https://github.com/Nuclei-Software/nuclei-sdk.git 7eb7bfa9ea4fbeacfafe1d5f77d5a0e6ed3922e7 gd32vf103
+hw/mcu/infineon/mtb-xmclib-cat3 https://github.com/Infineon/mtb-xmclib-cat3.git daf5500d03cba23e68c2f241c30af79cd9d63880 xmc4000
+hw/mcu/microchip https://github.com/hathach/microchip_driver.git 9e8b37e307d8404033bb881623a113931e1edf27 sam3x samd11 samd21 samd51 same5x same7x saml2x samg
+hw/mcu/mindmotion/mm32sdk https://github.com/hathach/mm32sdk.git 0b79559eb411149d36e073c1635c620e576308d4 mm32
+hw/mcu/nordic/nrfx https://github.com/NordicSemiconductor/nrfx.git 2527e3c8449cfd38aee41598e8af8492f410ed15 nrf
+hw/mcu/nuvoton https://github.com/majbthrd/nuc_driver.git 2204191ec76283371419fbcec207da02e1bc22fa nuc
+hw/mcu/nxp/lpcopen https://github.com/hathach/nxp_lpcopen.git 84e0bd3e43910aaf71eefd62075cf57495418312 lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43
+hw/mcu/nxp/mcux-sdk https://github.com/hathach/mcux-sdk.git 950819b7de9b32f92c3edf396bc5ffb8d66e7009 kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt
+hw/mcu/raspberry_pi/Pico-PIO-USB https://github.com/sekigon-gonnoc/Pico-PIO-USB.git d00a10a8c425d0d40f81b87169102944b01f3bb3 rp2040
+hw/mcu/renesas/fsp https://github.com/renesas/fsp.git d52e5a6a59b7c638da860c2bb309b6e78e752ff8 ra
+hw/mcu/renesas/rx https://github.com/kkitayam/rx_device.git 706b4e0cf485605c32351e2f90f5698267996023 rx
+hw/mcu/silabs/cmsis-dfp-efm32gg12b https://github.com/cmsis-packs/cmsis-dfp-efm32gg12b.git f1c31b7887669cb230b3ea63f9b56769078960bc efm32
+hw/mcu/sony/cxd56/spresense-exported-sdk https://github.com/sonydevworld/spresense-exported-sdk.git 2ec2a1538362696118dc3fdf56f33dacaf8f4067 spresense
+hw/mcu/st/cmsis_device_f0 https://github.com/STMicroelectronics/cmsis_device_f0.git 2fc25ee22264bc27034358be0bd400b893ef837e stm32f0
+hw/mcu/st/cmsis_device_f1 https://github.com/STMicroelectronics/cmsis_device_f1.git 6601104a6397299b7304fd5bcd9a491f56cb23a6 stm32f1
+hw/mcu/st/cmsis_device_f2 https://github.com/STMicroelectronics/cmsis_device_f2.git 182fcb3681ce116816feb41b7764f1b019ce796f stm32f2
+hw/mcu/st/cmsis_device_f3 https://github.com/STMicroelectronics/cmsis_device_f3.git 5e4ee5ed7a7b6c85176bb70a9fd3c72d6eb99f1b stm32f3
+hw/mcu/st/cmsis_device_f4 https://github.com/STMicroelectronics/cmsis_device_f4.git 2615e866fa48fe1ff1af9e31c348813f2b19e7ec stm32f4
+hw/mcu/st/cmsis_device_f7 https://github.com/STMicroelectronics/cmsis_device_f7.git fc676ef1ad177eb874eaa06444d3d75395fc51f4 stm32f7
+hw/mcu/st/cmsis_device_g0 https://github.com/STMicroelectronics/cmsis_device_g0.git 3a23e1224417f3f2d00300ecd620495e363f2094 stm32g0
+hw/mcu/st/cmsis_device_g4 https://github.com/STMicroelectronics/cmsis_device_g4.git ce822adb1dc552b3aedd13621edbc7fdae124878 stm32g4
+hw/mcu/st/cmsis_device_h7 https://github.com/STMicroelectronics/cmsis_device_h7.git 60dc2c913203dc8629dc233d4384dcc41c91e77f stm32h7
+hw/mcu/st/cmsis_device_l0 https://github.com/STMicroelectronics/cmsis_device_l0.git 06748ca1f93827befdb8b794402320d94d02004f stm32l0
+hw/mcu/st/cmsis_device_l1 https://github.com/STMicroelectronics/cmsis_device_l1.git 7f16ec0a1c4c063f84160b4cc6bf88ad554a823e stm32l1
+hw/mcu/st/cmsis_device_l4 https://github.com/STMicroelectronics/cmsis_device_l4.git 6ca7312fa6a5a460b5a5a63d66da527fdd8359a6 stm32l4
+hw/mcu/st/cmsis_device_l5 https://github.com/STMicroelectronics/cmsis_device_l5.git d922865fc0326a102c26211c44b8e42f52c1e53d stm32l5
+hw/mcu/st/cmsis_device_u5 https://github.com/STMicroelectronics/cmsis_device_u5.git 06d7edade7167b0eafdd550bf77cfc4fa98eae2e stm32u5
+hw/mcu/st/cmsis_device_wb https://github.com/STMicroelectronics/cmsis_device_wb.git 9c5d1920dd9fabbe2548e10561d63db829bb744f stm32wb
+hw/mcu/st/stm32f0xx_hal_driver https://github.com/STMicroelectronics/stm32f0xx_hal_driver.git 0e95cd88657030f640a11e690a8a5186c7712ea5 stm32f0
+hw/mcu/st/stm32f1xx_hal_driver https://github.com/STMicroelectronics/stm32f1xx_hal_driver.git 1dd9d3662fb7eb2a7f7d3bc0a4c1dc7537915a29 stm32f1
+hw/mcu/st/stm32f2xx_hal_driver https://github.com/STMicroelectronics/stm32f2xx_hal_driver.git c75ace9b908a9aca631193ebf2466963b8ea33d0 stm32f2
+hw/mcu/st/stm32f3xx_hal_driver https://github.com/STMicroelectronics/stm32f3xx_hal_driver.git 1761b6207318ede021706e75aae78f452d72b6fa stm32f3
+hw/mcu/st/stm32f4xx_hal_driver https://github.com/STMicroelectronics/stm32f4xx_hal_driver.git 04e99fbdabd00ab8f370f377c66b0a4570365b58 stm32f4
+hw/mcu/st/stm32f7xx_hal_driver https://github.com/STMicroelectronics/stm32f7xx_hal_driver.git f7ffdf6bf72110e58b42c632b0a051df5997e4ee stm32f7
+hw/mcu/st/stm32g0xx_hal_driver https://github.com/STMicroelectronics/stm32g0xx_hal_driver.git e911b12c7f67084d7f6b76157a4c0d4e2ec3779c stm32g0
+hw/mcu/st/stm32g4xx_hal_driver https://github.com/STMicroelectronics/stm32g4xx_hal_driver.git 8b4518417706d42eef5c14e56a650005abf478a8 stm32g4
+hw/mcu/st/stm32h7xx_hal_driver https://github.com/STMicroelectronics/stm32h7xx_hal_driver.git d8461b980b59b1625207d8c4f2ce0a9c2a7a3b04 stm32h7
+hw/mcu/st/stm32l0xx_hal_driver https://github.com/STMicroelectronics/stm32l0xx_hal_driver.git fbdacaf6f8c82a4e1eb9bd74ba650b491e97e17b stm32l0
+hw/mcu/st/stm32l1xx_hal_driver https://github.com/STMicroelectronics/stm32l1xx_hal_driver.git 44efc446fa69ed8344e7fd966e68ed11043b35d9 stm32l1
+hw/mcu/st/stm32l4xx_hal_driver https://github.com/STMicroelectronics/stm32l4xx_hal_driver.git aee3d5bf283ae5df87532b781bdd01b7caf256fc stm32l4
+hw/mcu/st/stm32l5xx_hal_driver https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git 675c32a75df37f39d50d61f51cb0dcf53f07e1cb stm32l5
+hw/mcu/st/stm32u5xx_hal_driver https://github.com/STMicroelectronics/stm32u5xx_hal_driver.git 4d93097a67928e9377e655ddd14622adc31b9770 stm32u5
+hw/mcu/st/stm32wbxx_hal_driver https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git 2c5f06638be516c1b772f768456ba637f077bac8 stm32wb
+hw/mcu/ti https://github.com/hathach/ti_driver.git 143ed6cc20a7615d042b03b21e070197d473e6e5 msp430 msp432e4 tm4c123
+hw/mcu/wch/ch32f20x https://github.com/openwch/ch32f20x.git 77c4095087e5ed2c548ec9058e655d0b8757663b ch32f20x
+hw/mcu/wch/ch32v307 https://github.com/openwch/ch32v307.git 17761f5cf9dbbf2dcf665b7c04934188add20082 ch32v307
+lib/CMSIS_5 https://github.com/ARM-software/CMSIS_5.git 20285262657d1b482d132d20d755c8c330d55c1f imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf ra saml2xstm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h7 stm32l0 stm32l1 stm32l4 stm32l5 stm32u5 stm32wb
+lib/FreeRTOS-Kernel https://github.com/FreeRTOS/FreeRTOS-Kernel.git 4ff01a7a4a51f53b44496aefee1e3c0071b7b173 all
+lib/lwip https://github.com/lwip-tcpip/lwip.git 159e31b689577dbf69cf0683bbaffbd71fa5ee10 all
+lib/sct_neopixel https://github.com/gsteiert/sct_neopixel.git e73e04ca63495672d955f9268e003cffe168fcd8 lpc55
+tools/uf2 https://github.com/microsoft/uf2.git 19615407727073e36d81bf239c52108ba92e7660 all
+======================================== ============================================================== ======================================== =======================================================================================================================================================================================================
diff --git a/docs/reference/getting_started.rst b/docs/reference/getting_started.rst
index e328757ba..3db3fa206 100644
--- a/docs/reference/getting_started.rst
+++ b/docs/reference/getting_started.rst
@@ -5,8 +5,7 @@ Getting Started
Add TinyUSB to your project
---------------------------
-It is relatively simple to incorporate tinyusb to your (existing) project
-
+It is relatively simple to incorporate tinyusb to your project
* Copy or ``git submodule`` this repo into your project in a subfolder. Let's say it is *your_project/tinyusb*
* Add all the .c in the ``tinyusb/src`` folder to your project
@@ -44,43 +43,52 @@ For your convenience, TinyUSB contains a handful of examples for both host and d
$ git clone https://github.com/hathach/tinyusb tinyusb
$ cd tinyusb
-Some TinyUSB examples also requires external submodule libraries in ``/lib`` such as FreeRTOS, Lightweight IP to build. Run following command to fetch them
+Some ports will also require a port-specific SDK (e.g. RP2040) or binary (e.g. Sony Spresense) to build examples. They are out of scope for tinyusb, you should download/install it first according to its manufacturer guide.
+
+Dependencies
+^^^^^^^^^^^^
+
+The hardware code is located in ``hw/bsp`` folder, and is organized by family/boards. e.g raspberry_pi_pico is located in ``hw/bsp/rp2040/boards/raspberry_pi_pico`` where FAMILY=rp2040 and BOARD=raspberry_pi_pico. Before building, we firstly need to download dependencies such as: MCU low-level peripheral driver and external libraries e.g FreeRTOS (required by some examples). We can do that by either ways:
+
+1. Run ``tools/get_deps.py {FAMILY}`` script to download all dependencies for a family as follow. Note: For TinyUSB developer to download all dependencies, use FAMILY=all.
.. code-block::
- $ git submodule update --init lib
+ $ python tools/get_deps.py rp2040
-Some ports will also require a port-specific SDK (e.g. RP2040) or binary (e.g. Sony Spresense) to build examples. They are out of scope for tinyusb, you should download/install it first according to its manufacturer guide.
+2. Or run the ``get-deps`` target in one of the example folder as follow.
+
+.. code-block::
+
+ $ cd examples/device/cdc_msc
+ $ make BOARD=raspberry_pi_pico get-deps
+
+You only need to do this once per family. Check out `complete list of dependencies and their designated path here `_
Build
^^^^^
-To build example, first change directory to an example folder.
+To build example, first change directory to an example folder.
.. code-block::
$ cd examples/device/cdc_msc
-Before building, we need to download MCU driver submodule to provide low-level MCU peripheral's driver first. Run the ``get-deps`` target in one of the example folder as follow. You only need to do this once per mcu
+Then compile with ``make BOARD={board_name} all`` , for example
.. code-block::
- $ make BOARD=feather_nrf52840_express get-deps
+ $ make BOARD=raspberry_pi_pico all
-
-Some modules (e.g. RP2040 and ESP32s2) require the project makefiles to be customized using CMake. If necessary apply any setup steps for the platform's SDK.
-
-Then compile with ``make BOARD=[board_name] all``\ , for example
+Note: some examples especially those that uses Vendor class (e.g webUSB) may requires udev permission on Linux (and/or macOS) to access usb device. It depends on your OS distro, typically copy ``99-tinyusb.rules`` and reload your udev is good to go
.. code-block::
- $ make BOARD=feather_nrf52840_express all
+ $ cp examples/device/99-tinyusb.rules /etc/udev/rules.d/
+ $ sudo udevadm control --reload-rules && sudo udevadm trigger
-Note: ``BOARD`` can be found as directory name in ``hw/bsp``\ , either in its family/boards or directly under bsp (no family).
-Note: some examples especially those that uses Vendor class (e.g webUSB) may requires udev permission on Linux (and/or macOS) to access usb device. It depends on your OS distro, typically copy ``/examples/device/99-tinyusb.rules`` file to /etc/udev/rules.d/ then run ``sudo udevadm control --reload-rules && sudo udevadm trigger`` is good enough.
-
-Port Selection
-~~~~~~~~~~~~~~
+RootHub Port Selection
+~~~~~~~~~~~~~~~~~~~~~~
If a board has several ports, one port is chosen by default in the individual board.mk file. Use option ``PORT=x`` To choose another port. For example to select the HS port of a STM32F746Disco board, use:
@@ -118,7 +126,7 @@ To compile for debugging add ``DEBUG=1``\ , for example
Log
~~~
-Should you have an issue running example and/or submitting an bug report. You could enable TinyUSB built-in debug logging with optional ``LOG=``. LOG=1 will only print out error message, LOG=2 print more information with on-going events. LOG=3 or higher is not used yet.
+Should you have an issue running example and/or submitting an bug report. You could enable TinyUSB built-in debug logging with optional ``LOG=``. LOG=1 will only print out error message, LOG=2 print more information with on-going events. LOG=3 or higher is not used yet.
.. code-block::
@@ -127,7 +135,7 @@ Should you have an issue running example and/or submitting an bug report. You co
Logger
~~~~~~
-By default log message is printed via on-board UART which is slow and take lots of CPU time comparing to USB speed. If your board support on-board/external debugger, it would be more efficient to use it for logging. There are 2 protocols:
+By default log message is printed via on-board UART which is slow and take lots of CPU time comparing to USB speed. If your board support on-board/external debugger, it would be more efficient to use it for logging. There are 2 protocols:
* `LOGGER=rtt`: use `Segger RTT protocol `_
@@ -170,7 +178,10 @@ Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can
$ make BOARD=feather_nrf52840_express all uf2
IAR Support
-^^^^^^^^^^^
+-----------
+
+Use project connection
+^^^^^^^^^^^^^^^^^^^^^^
IAR Project Connection files are provided to import TinyUSB stack into your project.
@@ -178,24 +189,24 @@ IAR Project Connection files are provided to import TinyUSB stack into your proj
* Take example of STM32F0:
-
+
- You need `stm32l0xx.h`, `startup_stm32f0xx.s`, `system_stm32f0xx.c`.
- `STM32L0xx_HAL_Driver` is only needed to run examples, TinyUSB stack itself doesn't rely on MCU's SDKs.
-* Open `Tools -> Configure Custom Argument Variables` (Switch to `Global` tab if you want to do it for all your projects)
+* Open ``Tools -> Configure Custom Argument Variables`` (Switch to `Global` tab if you want to do it for all your projects)
Click `New Group ...`, name it to `TUSB`, Click `Add Variable ...`, name it to `TUSB_DIR`, change it's value to the path of your TinyUSB stack,
for example `C:\\tinyusb`
Import stack only
~~~~~~~~~~~~~~~~~
-1. Open `Project -> Add project Connection ...`, click `OK`, choose `tinyusb\\tools\\iar_template.ipcf`.
+1. Open ``Project -> Add project Connection ...``, click `OK`, choose `tinyusb\\tools\\iar_template.ipcf`.
Run examples
~~~~~~~~~~~~
-1. (Python3 is needed) Run `iar_gen.py` to generate .ipcf files of examples:
+1. (Python3 is needed) Run ``iar_gen.py`` to generate .ipcf files of examples:
.. code-block::
@@ -204,3 +215,15 @@ Run examples
2. Open `Project -> Add project Connection ...`, click `OK`, choose `tinyusb\\examples\\(.ipcf of example)`.
For example `C:\\tinyusb\\examples\\device\\cdc_msc\\iar_cdc_msc.ipcf`
+
+Native CMake support (9.50.1+)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+With 9.50.1 release, IAR added experimental native CMake support (strangely not mentioned in public release note). Now it's possible to import CMakeLists.txt then build and debug as a normal project.
+
+Following these steps:
+
+1. Add IAR compiler binary path to system ``PATH`` environment variable, such as ``C:\Program Files\IAR Systems\Embedded Workbench 9.2\arm\bin``.
+2. Create new project in IAR, in Tool chain dropdown menu, choose CMake for Arm then Import ``CMakeLists.txt`` from chosen example directory.
+3. Set up board option in ``Option - CMake/CMSIS-TOOLBOX - CMake``, for example :code:`-DBOARD=stm32f439nucleo -DTOOLCHAIN=iar`, **Uncheck 'Override tools in env'**.
+4. (For debug only) Choose correct CPU model in ``Option - General Options - Target``, to profit register and memory view.
diff --git a/docs/reference/index.rst b/docs/reference/index.rst
index 292fb1a93..9ecdf619b 100644
--- a/docs/reference/index.rst
+++ b/docs/reference/index.rst
@@ -4,44 +4,69 @@ Reference
.. figure:: ../assets/stack.svg
:width: 1600px
- :alt: stackup
+ :alt: TinyUSB
+
+::
+
+ .
+ âââ docs # Documentation
+ âââ examples # Examples with make and cmake build system
+ âââ hw
+ â âââ bsp # Supported boards source files
+ â âââ mcu # Low level mcu core & peripheral drivers
+ âââ lib # Sources from 3rd party such as freeRTOS, fatfs ...
+ âââ src # All sources files for TinyUSB stack itself.
+ âââ test # Tests: unit test, fuzzing, hardware test
+ âââ tools # Files used internally
- representation of the TinyUSB stack.
Device Stack
============
-Supports multiple device configurations by dynamically changing usb descriptors. Low power functions such like suspend, resume, and remote wakeup. Following device classes are supported:
+Supports multiple device configurations by dynamically changing USB descriptors, low power functions such like suspend, resume, and remote wakeup. The following device classes are supported:
- Audio Class 2.0 (UAC2)
- Bluetooth Host Controller Interface (BTH HCI)
-- Communication Class (CDC)
-- Device Firmware Update (DFU): DFU mode (WIP) and Runtinme
+- Communication Device Class (CDC)
+- Device Firmware Update (DFU): DFU mode (WIP) and Runtime
- Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ...
- Mass Storage Class (MSC): with multiple LUNs
- Musical Instrument Digital Interface (MIDI)
-- Network with RNDIS, CDC-ECM (work in progress)
-- USB Test and Measurement Class (USBTMC)
+- Network with RNDIS, Ethernet Control Model (ECM), Network Control Model (NCM)
+- Test and Measurement Class (USBTMC)
+- Video class 1.5 (UVC): work in progress
- Vendor-specific class support with generic In & Out endpoints. Can be used with MS OS 2.0 compatible descriptor to load winUSB driver without INF file.
- `WebUSB `__ with vendor-specific class
-If you have special need, `usbd_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. Here is how RPi team add their reset interface `raspberrypi/pico-sdk#197 `__
+If you have a special requirement, `usbd_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. Here is how the RPi team added their reset interface `raspberrypi/pico-sdk#197 `_
Host Stack
==========
- Human Interface Device (HID): Keyboard, Mouse, Generic
- Mass Storage Class (MSC)
-- Hub currently only supports 1 level of hub (due to my laziness)
+- Communication Device Class: CDC-ACM
+- Vendor serial over USB: FTDI, CP210x
+- Hub with multiple-level support
+
+Similar to the Device Stack, if you have a special requirement, `usbh_app_driver_get_cb()` can be used to write your own class driver without modifying the stack.
+
+TypeC PD Stack
+==============
+
+- Power Delivery 3.0 (PD3.0) with USB Type-C support (WIP)
+- Super early stage, only for testing purpose
+- Only support STM32 G4
OS Abstraction layer
====================
-TinyUSB is completely thread-safe by pushing all ISR events into a central queue, then process it later in the non-ISR context task function. It also uses semaphore/mutex to access shared resources such as CDC FIFO. Therefore the stack needs to use some of OS's basic APIs. Following OSes are already supported out of the box.
+TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR) events into a central queue, then processing them later in the non-ISR context task function. It also uses semaphore/mutex to access shared resources such as Communication Device Class (CDC) FIFO. Therefore the stack needs to use some of the OS's basic APIs. Following OSes are already supported out of the box.
- **No OS**
- **FreeRTOS**
-- **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its `own repo `__
+- `RT-Thread `_: `repo `_
+- **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its `own repo `_
License
=======
@@ -56,4 +81,5 @@ Index
supported
getting_started
+ dependencies
concurrency
diff --git a/docs/reference/supported.rst b/docs/reference/supported.rst
index 7ec568ede..7e7be25a4 100644
--- a/docs/reference/supported.rst
+++ b/docs/reference/supported.rst
@@ -8,6 +8,12 @@ Supported MCUs
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
| Manufacturer | Family | Device | Host | Highspeed | Driver | Note |
+==============+=======================+========+======+===========+===================+==============+
+| Allwinner | F1C100s/F1C200s | â | | â | sunxi | musb variant |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| Analog | MAX3421E | | â | â | max3421 | via SPI |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| Brigetek | FT90x | â | | â | ft9xx | |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
| Broadcom | BCM2711, BCM2837 | â | | â | dwc2 | |
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
| Dialog | DA1469x | â | â | â | da146xx | |
@@ -17,36 +23,46 @@ Supported MCUs
| GigaDevice | GD32VF103 | â | | â | dwc2 | |
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
| Infineon | XMC4500 | â | | â | dwc2 | |
-+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
-| MicroChip | SAM D11, D21 | â | | â | samd | |
-| +-----------------------+--------+------+-----------+-------------------+--------------+
-| | SAM D51, E5x | â | | â | samd | |
-| +-----------------------+--------+------+-----------+-------------------+--------------+
-| | SAM G55 | â | | â | samg | |
-| +-----------------------+--------+------+-----------+-------------------+--------------+
-| | SAM L21, L22 | â | | â | samd | |
-| +-----------------------+--------+------+-----------+-------------------+--------------+
-| | SAM E70,S70,V70,V71 | â | | â | samx7x | |
-+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
++--------------+-----+-----------------+--------+------+-----------+-------------------+--------------+
+| MicroChip | SAM | D11, D21 | â | | â | samd | |
+| | +-----------------+--------+------+-----------+-------------------+--------------+
+| | | D51, E5x | â | | â | samd | |
+| | +-----------------+--------+------+-----------+-------------------+--------------+
+| | | G55 | â | | â | samg | |
+| | +-----------------+--------+------+-----------+-------------------+--------------+
+| | | L21, L22 | â | | â | samd | |
+| | +-----------------+--------+------+-----------+-------------------+--------------+
+| | | E70,S70,V70,V71 | â | | â | samx7x | |
+| +-----+-----------------+--------+------+-----------+-------------------+--------------+
+| | PIC | 24 | â | | | pic | ci_fs variant|
+| | +-----------------+--------+------+-----------+-------------------+--------------+
+| | | 32 mm, mk, mx | â | | | pic | ci_fs variant|
+| | +-----------------+--------+------+-----------+-------------------+--------------+
+| | | dsPIC33 | â | | | pic | ci_fs variant|
+| | +-----------------+--------+------+-----------+-------------------+--------------+
+| | | 32mz | â | | | pic32mz | musb variant |
++--------------+-----+-----------------+--------+------+-----------+-------------------+--------------+
+| Mind Montion | mm32 | â | | â | mm32f327x_otg | ci_fs variant|
++--------------+-----+-----------------+--------+------+-----------+-------------------+--------------+
| NordicSemi | nRF52833, nRF52840 | â | â | â | nrf5x | |
| +-----------------------+--------+------+-----------+-------------------+--------------+
| | nRF5340 | â | â | â | nrf5x | |
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
-| Nuvoton | NUC120 | â | â | â | | |
+| Nuvoton | NUC120 | â | â | â | nuc120 | |
| +-----------------------+--------+------+-----------+-------------------+--------------+
-| | NUC121/NUC125 | â | â | â | | |
+| | NUC121/NUC125 | â | â | â | nuc121 | |
| +-----------------------+--------+------+-----------+-------------------+--------------+
-| | NUC126 | â | â | â | | |
+| | NUC126 | â | â | â | nuc121 | |
| +-----------------------+--------+------+-----------+-------------------+--------------+
-| | NUC505 | â | | â | | |
+| | NUC505 | â | | â | nuc505 | |
+--------------+---------+-------------+--------+------+-----------+-------------------+--------------+
| NXP | iMXRT | RT10xx | â | â | â | ci_hs | |
| | +-------------+--------+------+-----------+-------------------+--------------+
| | | RT11xx | â | â | â | ci_hs | |
| +---------+-------------+--------+------+-----------+-------------------+--------------+
-| | Kinetis | KL25 | â | â | â | | |
+| | Kinetis | KL | â | â | â | ci_fs, khci | |
| | +-------------+--------+------+-----------+-------------------+--------------+
-| | | K32L2 | â | | â | | |
+| | | K32L2 | â | | â | khci | ci_fs variant|
| +---------+-------------+--------+------+-----------+-------------------+--------------+
| | LPC | 11u, 13, 15 | â | â | â | lpc_ip3511 | |
| | +-------------+--------+------+-----------+-------------------+--------------+
@@ -59,11 +75,17 @@ Supported MCUs
| | | 54 | â | | â | lpc_ip3511 | |
| | +-------------+--------+------+-----------+-------------------+--------------+
| | | 55 | â | | â | lpc_ip3511 | |
+| +---------+-------------+--------+------+-----------+-------------------+--------------+
+| | MCX | N9 | â | | â | ci_fs, ci_hs | |
+--------------+---------+-------------+--------+------+-----------+-------------------+--------------+
| Raspberry Pi | RP2040 | â | â | â | rp2040, pio_usb | |
-+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
-| Renesas | RX 63N, 65N, 72N | â | â | â | usba | |
-+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
++--------------+-----+-----------------+--------+------+-----------+-------------------+--------------+
+| Renesas | RX | 63N, 65N, 72N | â | â | â | rusb2 | |
+| +-----+-----------------+--------+------+-----------+-------------------+--------------+
+| | RA | 4M1, 4M3, 6M1 | â | â | â | rusb2 | |
+| | +-----------------+--------+------+-----------+-------------------+--------------+
+| | | 6M5 | â | â | â | rusb2 | |
++--------------+-----+-----------------+--------+------+-----------+-------------------+--------------+
| Silabs | EFM32GG12 | â | | â | dwc2 | |
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
| Sony | CXD56 | â | â | â | cxd56 | |
@@ -94,7 +116,7 @@ Supported MCUs
| +----+------------------+--------+------+-----------+-------------------+--------------+
| | L4+ | â | | | dwc2 | |
| +-----------------------+--------+------+-----------+-------------------+--------------+
-| | U5 | â | | | dwc2 | |
+| | U5 | â | | â | dwc2 | |
| +-----------------------+--------+------+-----------+-------------------+--------------+
| | WBx5 | â | | | stm32_fsdev | |
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
@@ -107,6 +129,8 @@ Supported MCUs
| ValentyUSB | eptri | â | â | â | eptri | |
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
| WCH | CH32V307 | â | | â | ch32v307 | |
+| +-----------------------+--------+------+-----------+-------------------+--------------+
+| | CH32F20x | â | | â | ch32f205 | |
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
@@ -173,7 +197,7 @@ SAMD11 & SAMD21
- `Adafruit Feather M0 Express `__
- `Adafruit ItsyBitsy M0 Express `__
- `Adafruit Metro M0 Express `__
-- `Great Scott Gadgets LUNA `__
+- `Great Scott Gadgets Cynthion `__
- `Microchip SAMD11 Xplained Pro `__
- `Microchip SAMD21 Xplained Pro `__
- `Seeeduino Xiao `__
@@ -251,6 +275,7 @@ Kinetis
^^^^^^^
- `Freedom FRDM-KL25Z `__
+- `Freedom FRDM-K32L2A4S `__
- `Freedom FRDM-K32L2B3 `__
- `KUIIC `__
@@ -275,7 +300,6 @@ LPC 18-43
- `Embedded Artists LPC4357 Developer Kit `__
- `Keil MCB1800 Evaluation Board `__
- `LPCXpresso18S37 Development Board `__
-- `NGX LPC4330-Xplorer `__
LPC 51
^^^^^^
@@ -295,8 +319,17 @@ LPC55
- `LPCXpresso 55s69 EVK `__
- `MCU-Link `__
-Renesas RX
-----------
+Renesas
+-------
+
+RA
+^^
+
+- `Evaluation Kit for RA4M1 `__
+- `Evaluation Kit for RA4M3 `__
+
+RX
+^^
- `GR-CITRUS `__
- `Renesas RX65N Target Board `__
@@ -403,4 +436,5 @@ Tomu
WCH
---
-- `CH32V307V-R1-1v0 `
+- `CH32V307V-R1-1v0 `__
+- `CH32F205R-R0-1v0 `__
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 15022e147..ad5c89922 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,4 +1,4 @@
-sphinx~=3.0
+sphinx>=5.0
furo>=2020.12.30.b24
sphinx-autodoc-typehints>=1.10
-jinja2==3.0.3
+jinja2>=3.0.3
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
new file mode 100644
index 000000000..c603d0c22
--- /dev/null
+++ b/examples/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.17)
+
+#set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../hw/bsp/family_support.cmake)
+
+project(tinyusb_examples C CXX ASM)
+
+add_subdirectory(device)
+add_subdirectory(dual)
+add_subdirectory(host)
+add_subdirectory(typec)
diff --git a/examples/build_system/cmake/cpu/cortex-m0.cmake b/examples/build_system/cmake/cpu/cortex-m0.cmake
new file mode 100644
index 000000000..62019d90d
--- /dev/null
+++ b/examples/build_system/cmake/cpu/cortex-m0.cmake
@@ -0,0 +1,22 @@
+if (TOOLCHAIN STREQUAL "gcc")
+ set(TOOLCHAIN_COMMON_FLAGS
+ -mthumb
+ -mcpu=cortex-m0plus
+ -mfloat-abi=soft
+ )
+ set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "clang")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --target=arm-none-eabi
+ -mcpu=cortex-m0
+ )
+ set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "iar")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --cpu cortex-m0
+ )
+ set(FREERTOS_PORT IAR_ARM_CM0 CACHE INTERNAL "")
+
+endif ()
diff --git a/examples/build_system/cmake/cpu/cortex-m0plus.cmake b/examples/build_system/cmake/cpu/cortex-m0plus.cmake
new file mode 100644
index 000000000..ddf0f16af
--- /dev/null
+++ b/examples/build_system/cmake/cpu/cortex-m0plus.cmake
@@ -0,0 +1,22 @@
+if (TOOLCHAIN STREQUAL "gcc")
+ set(TOOLCHAIN_COMMON_FLAGS
+ -mthumb
+ -mcpu=cortex-m0plus
+ -mfloat-abi=soft
+ )
+ set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "clang")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --target=arm-none-eabi
+ -mcpu=cortex-m0plus
+ )
+ set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "iar")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --cpu cortex-m0
+ )
+ set(FREERTOS_PORT IAR_ARM_CM0 CACHE INTERNAL "")
+
+endif ()
diff --git a/examples/build_system/cmake/cpu/cortex-m23.cmake b/examples/build_system/cmake/cpu/cortex-m23.cmake
new file mode 100644
index 000000000..00382ed9b
--- /dev/null
+++ b/examples/build_system/cmake/cpu/cortex-m23.cmake
@@ -0,0 +1,22 @@
+if (TOOLCHAIN STREQUAL "gcc")
+ set(TOOLCHAIN_COMMON_FLAGS
+ -mthumb
+ -mcpu=cortex-m23
+ -mfloat-abi=soft
+ )
+ set(FREERTOS_PORT GCC_ARM_CM23_NTZ_NONSECURE CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "clang")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --target=arm-none-eabi
+ -mcpu=cortex-m23
+ )
+ set(FREERTOS_PORT GCC_ARM_CM23_NTZ_NONSECURE CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "iar")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --cpu cortex-m23
+ )
+ set(FREERTOS_PORT IAR_ARM_CM23_NTZ_NONSECURE CACHE INTERNAL "")
+
+endif ()
diff --git a/examples/build_system/cmake/cpu/cortex-m3.cmake b/examples/build_system/cmake/cpu/cortex-m3.cmake
new file mode 100644
index 000000000..27888604e
--- /dev/null
+++ b/examples/build_system/cmake/cpu/cortex-m3.cmake
@@ -0,0 +1,21 @@
+if (TOOLCHAIN STREQUAL "gcc")
+ set(TOOLCHAIN_COMMON_FLAGS
+ -mthumb
+ -mcpu=cortex-m3
+ )
+ set(FREERTOS_PORT GCC_ARM_CM3 CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "clang")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --target=arm-none-eabi
+ -mcpu=cortex-m3
+ )
+ set(FREERTOS_PORT GCC_ARM_CM3 CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "iar")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --cpu cortex-m3
+ )
+ set(FREERTOS_PORT IAR_ARM_CM3 CACHE INTERNAL "")
+
+endif ()
diff --git a/examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake b/examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake
new file mode 100644
index 000000000..51fd70b0e
--- /dev/null
+++ b/examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake
@@ -0,0 +1,18 @@
+if (TOOLCHAIN STREQUAL "gcc")
+ set(TOOLCHAIN_COMMON_FLAGS
+ -mthumb
+ -mcpu=cortex-m33+nodsp
+ -mfloat-abi=soft
+ )
+ set(FREERTOS_PORT GCC_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "clang")
+ message(FATAL_ERROR "Clang is not supported for this target")
+
+elseif (TOOLCHAIN STREQUAL "iar")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --cpu cortex-m33+nodsp
+ )
+ set(FREERTOS_PORT IAR_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "")
+
+endif ()
diff --git a/examples/build_system/cmake/cpu/cortex-m33.cmake b/examples/build_system/cmake/cpu/cortex-m33.cmake
new file mode 100644
index 000000000..d56d07ebc
--- /dev/null
+++ b/examples/build_system/cmake/cpu/cortex-m33.cmake
@@ -0,0 +1,25 @@
+if (TOOLCHAIN STREQUAL "gcc")
+ set(TOOLCHAIN_COMMON_FLAGS
+ -mthumb
+ -mcpu=cortex-m33
+ -mfloat-abi=hard
+ -mfpu=fpv5-sp-d16
+ )
+ set(FREERTOS_PORT GCC_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "clang")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --target=arm-none-eabi
+ -mcpu=cortex-m33
+ -mfpu=fpv5-sp-d16
+ )
+ set(FREERTOS_PORT GCC_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "iar")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --cpu cortex-m33
+ --fpu VFPv5-SP
+ )
+ set(FREERTOS_PORT IAR_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "")
+
+endif ()
diff --git a/examples/build_system/cmake/cpu/cortex-m4.cmake b/examples/build_system/cmake/cpu/cortex-m4.cmake
new file mode 100644
index 000000000..9cdadc6f8
--- /dev/null
+++ b/examples/build_system/cmake/cpu/cortex-m4.cmake
@@ -0,0 +1,32 @@
+if (TOOLCHAIN STREQUAL "gcc")
+ set(TOOLCHAIN_COMMON_FLAGS
+ -mthumb
+ -mcpu=cortex-m4
+ -mfloat-abi=hard
+ -mfpu=fpv4-sp-d16
+ )
+ if (NOT DEFINED FREERTOS_PORT)
+ set(FREERTOS_PORT GCC_ARM_CM4F CACHE INTERNAL "")
+ endif ()
+
+elseif (TOOLCHAIN STREQUAL "clang")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --target=arm-none-eabi
+ -mcpu=cortex-m4
+ -mfpu=fpv4-sp-d16
+ )
+ if (NOT DEFINED FREERTOS_PORT)
+ set(FREERTOS_PORT GCC_ARM_CM4F CACHE INTERNAL "")
+ endif ()
+
+elseif (TOOLCHAIN STREQUAL "iar")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --cpu cortex-m4
+ --fpu VFPv4_sp
+ )
+
+ if (NOT DEFINED FREERTOS_PORT)
+ set(FREERTOS_PORT IAR_ARM_CM4F CACHE INTERNAL "")
+ endif ()
+
+endif ()
diff --git a/examples/build_system/cmake/cpu/cortex-m7.cmake b/examples/build_system/cmake/cpu/cortex-m7.cmake
new file mode 100644
index 000000000..b41dfded5
--- /dev/null
+++ b/examples/build_system/cmake/cpu/cortex-m7.cmake
@@ -0,0 +1,25 @@
+if (TOOLCHAIN STREQUAL "gcc")
+ set(TOOLCHAIN_COMMON_FLAGS
+ -mthumb
+ -mcpu=cortex-m7
+ -mfloat-abi=hard
+ -mfpu=fpv5-d16
+ )
+ set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "clang")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --target=arm-none-eabi
+ -mcpu=cortex-m7
+ -mfpu=fpv5-d16
+ )
+ set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "iar")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --cpu cortex-m7
+ --fpu VFPv5_D16
+ )
+ set(FREERTOS_PORT IAR_ARM_CM7 CACHE INTERNAL "")
+
+endif ()
diff --git a/examples/build_system/cmake/cpu/msp430.cmake b/examples/build_system/cmake/cpu/msp430.cmake
new file mode 100644
index 000000000..584ec5741
--- /dev/null
+++ b/examples/build_system/cmake/cpu/msp430.cmake
@@ -0,0 +1,10 @@
+if (TOOLCHAIN STREQUAL "gcc")
+ set(FREERTOS_PORT GCC_MSP430F449 CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "clang")
+ message(FATAL_ERROR "Clang is not supported for this target")
+
+elseif (TOOLCHAIN STREQUAL "iar")
+ set(FREERTOS_PORT IAR_MSP430 CACHE INTERNAL "")
+
+endif ()
diff --git a/examples/build_system/cmake/toolchain/arm_clang.cmake b/examples/build_system/cmake/toolchain/arm_clang.cmake
new file mode 100644
index 000000000..754d672fd
--- /dev/null
+++ b/examples/build_system/cmake/toolchain/arm_clang.cmake
@@ -0,0 +1,21 @@
+if (NOT DEFINED CMAKE_C_COMPILER)
+ set(CMAKE_C_COMPILER "clang")
+endif ()
+
+if (NOT DEFINED CMAKE_CXX_COMPILER)
+ set(CMAKE_CXX_COMPILER "clang++")
+endif ()
+
+set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
+set(CMAKE_SIZE "llvm-size" CACHE FILEPATH "")
+set(CMAKE_OBJCOPY "llvm-objcopy" CACHE FILEPATH "")
+set(CMAKE_OBJDUMP "llvm-objdump" CACHE FILEPATH "")
+
+include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
+
+get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
+if (IS_IN_TRY_COMPILE)
+ set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib")
+ set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib")
+ cmake_print_variables(CMAKE_C_LINK_FLAGS)
+endif ()
diff --git a/examples/build_system/cmake/toolchain/arm_gcc.cmake b/examples/build_system/cmake/toolchain/arm_gcc.cmake
new file mode 100644
index 000000000..d3d73c629
--- /dev/null
+++ b/examples/build_system/cmake/toolchain/arm_gcc.cmake
@@ -0,0 +1,21 @@
+if (NOT DEFINED CMAKE_C_COMPILER)
+ set(CMAKE_C_COMPILER "arm-none-eabi-gcc")
+endif ()
+
+if (NOT DEFINED CMAKE_CXX_COMPILER)
+ set(CMAKE_CXX_COMPILER "arm-none-eabi-g++")
+endif ()
+
+set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
+set(CMAKE_SIZE "arm-none-eabi-size" CACHE FILEPATH "")
+set(CMAKE_OBJCOPY "arm-none-eabi-objcopy" CACHE FILEPATH "")
+set(CMAKE_OBJDUMP "arm-none-eabi-objdump" CACHE FILEPATH "")
+
+include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
+
+get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
+if (IS_IN_TRY_COMPILE)
+ set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib")
+ set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib")
+ cmake_print_variables(CMAKE_C_LINK_FLAGS)
+endif ()
diff --git a/examples/build_system/cmake/toolchain/arm_iar.cmake b/examples/build_system/cmake/toolchain/arm_iar.cmake
new file mode 100644
index 000000000..6d2219ca8
--- /dev/null
+++ b/examples/build_system/cmake/toolchain/arm_iar.cmake
@@ -0,0 +1,17 @@
+if (NOT DEFINED CMAKE_C_COMPILER)
+ set(CMAKE_C_COMPILER "iccarm")
+endif()
+
+if (NOT DEFINED CMAKE_CXX_COMPILER)
+ set(CMAKE_CXX_COMPILER "iccarm")
+endif()
+
+if (NOT DEFINED CMAKE_ASM_COMPILER)
+ set(CMAKE_ASM_COMPILER "iasmarm")
+endif()
+
+set(CMAKE_SIZE "size" CACHE FILEPATH "")
+set(CMAKE_OBJCOPY "ielftool" CACHE FILEPATH "")
+set(CMAKE_OBJDUMP "iefdumparm" CACHE FILEPATH "")
+
+include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
diff --git a/examples/build_system/cmake/toolchain/common.cmake b/examples/build_system/cmake/toolchain/common.cmake
new file mode 100644
index 000000000..688715914
--- /dev/null
+++ b/examples/build_system/cmake/toolchain/common.cmake
@@ -0,0 +1,64 @@
+include(CMakePrintHelpers)
+
+# ----------------------------------------------------------------------------
+# Common
+# ----------------------------------------------------------------------------
+set(CMAKE_SYSTEM_NAME Generic)
+set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
+
+# Look for includes and libraries only in the target system prefix.
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+
+# pass TOOLCHAIN_CPU to
+set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_SYSTEM_PROCESSOR)
+include(${CMAKE_CURRENT_LIST_DIR}/../cpu/${CMAKE_SYSTEM_PROCESSOR}.cmake)
+
+# ----------------------------------------------------------------------------
+# Compile flags
+# ----------------------------------------------------------------------------
+if (TOOLCHAIN STREQUAL "gcc")
+ list(APPEND TOOLCHAIN_COMMON_FLAGS
+ -fdata-sections
+ -ffunction-sections
+ -fsingle-precision-constant
+ -fno-strict-aliasing
+ )
+ list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS
+ -Wl,--print-memory-usage
+ -Wl,--gc-sections
+ -Wl,--cref
+ )
+
+elseif (TOOLCHAIN STREQUAL "iar")
+ #list(APPEND TOOLCHAIN_COMMON_FLAGS)
+ list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS
+ --diag_suppress=Li065
+ )
+
+elseif (TOOLCHAIN STREQUAL "clang")
+ list(APPEND TOOLCHAIN_COMMON_FLAGS
+ -fdata-sections
+ -ffunction-sections
+ -fno-strict-aliasing
+ )
+ list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS
+ -Wl,--print-memory-usage
+ -Wl,--gc-sections
+ -Wl,--cref
+ )
+endif ()
+
+# join the toolchain flags into a single string
+list(JOIN TOOLCHAIN_COMMON_FLAGS " " TOOLCHAIN_COMMON_FLAGS)
+foreach (LANG IN ITEMS C CXX ASM)
+ set(CMAKE_${LANG}_FLAGS_INIT ${TOOLCHAIN_COMMON_FLAGS})
+ # optimization flags for LOG, LOGGER ?
+ #set(CMAKE_${LANG}_FLAGS_RELEASE_INIT "-Os")
+ #set(CMAKE_${LANG}_FLAGS_DEBUG_INIT "-O0")
+endforeach ()
+
+# Linker
+list(JOIN TOOLCHAIN_EXE_LINKER_FLAGS " " CMAKE_EXE_LINKER_FLAGS_INIT)
diff --git a/examples/build_system/cmake/toolchain/msp430_gcc.cmake b/examples/build_system/cmake/toolchain/msp430_gcc.cmake
new file mode 100644
index 000000000..73368adba
--- /dev/null
+++ b/examples/build_system/cmake/toolchain/msp430_gcc.cmake
@@ -0,0 +1,15 @@
+if (NOT DEFINED CMAKE_C_COMPILER)
+ set(CMAKE_C_COMPILER "msp430-elf-gcc")
+endif ()
+
+if (NOT DEFINED CMAKE_CXX_COMPILER)
+ set(CMAKE_CXX_COMPILER "msp430-elf-g++")
+endif ()
+
+set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
+
+set(CMAKE_SIZE "msp430-elf-size" CACHE FILEPATH "")
+set(CMAKE_OBJCOPY "msp430-elf-objcopy" CACHE FILEPATH "")
+set(CMAKE_OBJDUMP "msp430-elf-objdump" CACHE FILEPATH "")
+
+include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
diff --git a/examples/build_system/make/cpu/arm1176.mk b/examples/build_system/make/cpu/arm1176.mk
new file mode 100644
index 000000000..022ccf7ad
--- /dev/null
+++ b/examples/build_system/make/cpu/arm1176.mk
@@ -0,0 +1,9 @@
+ifeq ($(TOOLCHAIN),gcc)
+ CFLAGS += \
+ -mcpu=arm1176jzf-s \
+
+else ifeq ($(TOOLCHAIN),iar)
+ #CFLAGS += --cpu cortex-a53
+ #ASFLAGS += --cpu cortex-a53
+
+endif
diff --git a/examples/build_system/make/cpu/cortex-a53.mk b/examples/build_system/make/cpu/cortex-a53.mk
new file mode 100644
index 000000000..42e522ecf
--- /dev/null
+++ b/examples/build_system/make/cpu/cortex-a53.mk
@@ -0,0 +1,12 @@
+ifeq ($(TOOLCHAIN),gcc)
+ CFLAGS += \
+ -mcpu=cortex-a53 \
+
+else ifeq ($(TOOLCHAIN),iar)
+ CFLAGS += \
+ --cpu cortex-a53 \
+
+ ASFLAGS += \
+ --cpu cortex-a53 \
+
+endif
diff --git a/examples/build_system/make/cpu/cortex-a72.mk b/examples/build_system/make/cpu/cortex-a72.mk
new file mode 100644
index 000000000..1b3d8da4a
--- /dev/null
+++ b/examples/build_system/make/cpu/cortex-a72.mk
@@ -0,0 +1,12 @@
+ifeq ($(TOOLCHAIN),gcc)
+ CFLAGS += \
+ -mcpu=cortex-a72 \
+
+else ifeq ($(TOOLCHAIN),iar)
+ CFLAGS += \
+ --cpu cortex-a72 \
+
+ ASFLAGS += \
+ --cpu cortex-a72 \
+
+endif
diff --git a/examples/build_system/make/cpu/cortex-m0.mk b/examples/build_system/make/cpu/cortex-m0.mk
new file mode 100644
index 000000000..c2c33a2ee
--- /dev/null
+++ b/examples/build_system/make/cpu/cortex-m0.mk
@@ -0,0 +1,22 @@
+ifeq ($(TOOLCHAIN),gcc)
+ CFLAGS += \
+ -mthumb \
+ -mcpu=cortex-m0 \
+ -mfloat-abi=soft \
+
+else ifeq ($(TOOLCHAIN),clang)
+ CFLAGS += \
+ --target=arm-none-eabi \
+ -mcpu=cortex-m0 \
+
+else ifeq ($(TOOLCHAIN),iar)
+ # IAR Flags
+ CFLAGS += --cpu cortex-m0
+ ASFLAGS += --cpu cortex-m0
+
+else
+ $(error "TOOLCHAIN is not supported")
+endif
+
+# For freeRTOS port source
+FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM0
diff --git a/examples/build_system/make/cpu/cortex-m0plus.mk b/examples/build_system/make/cpu/cortex-m0plus.mk
new file mode 100644
index 000000000..fe8feb227
--- /dev/null
+++ b/examples/build_system/make/cpu/cortex-m0plus.mk
@@ -0,0 +1,22 @@
+ifeq ($(TOOLCHAIN),gcc)
+ CFLAGS += \
+ -mthumb \
+ -mcpu=cortex-m0plus \
+ -mfloat-abi=soft \
+
+else ifeq ($(TOOLCHAIN),clang)
+ CFLAGS += \
+ --target=arm-none-eabi \
+ -mcpu=cortex-m0plus \
+
+else ifeq ($(TOOLCHAIN),iar)
+ # IAR Flags
+ CFLAGS += --cpu cortex-m0+
+ ASFLAGS += --cpu cortex-m0+
+
+else
+ $(error "TOOLCHAIN is not supported")
+endif
+
+# For freeRTOS port source
+FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM0
diff --git a/examples/build_system/make/cpu/cortex-m23.mk b/examples/build_system/make/cpu/cortex-m23.mk
new file mode 100644
index 000000000..7ab758352
--- /dev/null
+++ b/examples/build_system/make/cpu/cortex-m23.mk
@@ -0,0 +1,22 @@
+ifeq ($(TOOLCHAIN),gcc)
+ CFLAGS += \
+ -mthumb \
+ -mcpu=cortex-m23 \
+ -mfloat-abi=soft \
+
+else ifeq ($(TOOLCHAIN),clang)
+ CFLAGS += \
+ --target=arm-none-eabi \
+ -mcpu=cortex-m23 \
+
+else ifeq ($(TOOLCHAIN),iar)
+ # IAR Flags
+ CFLAGS += --cpu cortex-m23
+ ASFLAGS += --cpu cortex-m23
+
+else
+ $(error "TOOLCHAIN is not supported")
+endif
+
+# For freeRTOS port source
+FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM23
diff --git a/examples/build_system/make/cpu/cortex-m3.mk b/examples/build_system/make/cpu/cortex-m3.mk
new file mode 100644
index 000000000..b6325313f
--- /dev/null
+++ b/examples/build_system/make/cpu/cortex-m3.mk
@@ -0,0 +1,22 @@
+ifeq ($(TOOLCHAIN),gcc)
+ CFLAGS += \
+ -mthumb \
+ -mcpu=cortex-m3 \
+ -mfloat-abi=soft \
+
+else ifeq ($(TOOLCHAIN),clang)
+ CFLAGS += \
+ --target=arm-none-eabi \
+ -mcpu=cortex-m3 \
+
+else ifeq ($(TOOLCHAIN),iar)
+ # IAR Flags
+ CFLAGS += --cpu cortex-m3
+ ASFLAGS += --cpu cortex-m3
+
+else
+ $(error "TOOLCHAIN is not supported")
+endif
+
+# For freeRTOS port source
+FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM3
diff --git a/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk b/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk
new file mode 100644
index 000000000..405053dd0
--- /dev/null
+++ b/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk
@@ -0,0 +1,24 @@
+ifeq ($(TOOLCHAIN),gcc)
+ CFLAGS += \
+ -mthumb \
+ -mcpu=cortex-m33+nodsp \
+ -mfloat-abi=soft \
+
+else ifeq ($(TOOLCHAIN),clang)
+ CFLAGS += \
+ --target=arm-none-eabi \
+ -mcpu=cortex-m33 \
+ -mfpu=softvp \
+
+else ifeq ($(TOOLCHAIN),iar)
+ CFLAGS += \
+ --cpu cortex-m33+nodsp \
+
+ ASFLAGS += \
+ --cpu cortex-m33+nodsp \
+
+else
+ $(error "TOOLCHAIN is not supported")
+endif
+
+FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM33_NTZ/non_secure
diff --git a/examples/build_system/make/cpu/cortex-m33.mk b/examples/build_system/make/cpu/cortex-m33.mk
new file mode 100644
index 000000000..47b0eaecd
--- /dev/null
+++ b/examples/build_system/make/cpu/cortex-m33.mk
@@ -0,0 +1,27 @@
+ifeq ($(TOOLCHAIN),gcc)
+ CFLAGS += \
+ -mthumb \
+ -mcpu=cortex-m33 \
+ -mfloat-abi=hard \
+ -mfpu=fpv5-sp-d16 \
+
+else ifeq ($(TOOLCHAIN),clang)
+ CFLAGS += \
+ --target=arm-none-eabi \
+ -mcpu=cortex-m33 \
+ -mfpu=fpv5-sp-d16 \
+
+else ifeq ($(TOOLCHAIN),iar)
+ CFLAGS += \
+ --cpu cortex-m33 \
+ --fpu VFPv5-SP \
+
+ ASFLAGS += \
+ --cpu cortex-m33 \
+ --fpu VFPv5-SP \
+
+else
+ $(error "TOOLCHAIN is not supported")
+endif
+
+FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM33_NTZ/non_secure
diff --git a/examples/build_system/make/cpu/cortex-m4.mk b/examples/build_system/make/cpu/cortex-m4.mk
new file mode 100644
index 000000000..4e16819d1
--- /dev/null
+++ b/examples/build_system/make/cpu/cortex-m4.mk
@@ -0,0 +1,22 @@
+ifeq ($(TOOLCHAIN),gcc)
+ CFLAGS += \
+ -mthumb \
+ -mcpu=cortex-m4 \
+ -mfloat-abi=hard \
+ -mfpu=fpv4-sp-d16 \
+
+else ifeq ($(TOOLCHAIN),clang)
+ CFLAGS += \
+ --target=arm-none-eabi \
+ -mcpu=cortex-m4 \
+ -mfpu=fpv4-sp-d16 \
+
+else ifeq ($(TOOLCHAIN),iar)
+ CFLAGS += --cpu cortex-m4 --fpu VFPv4
+ ASFLAGS += --cpu cortex-m4 --fpu VFPv4
+
+else
+ $(error "TOOLCHAIN is not supported")
+endif
+
+FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM4F
diff --git a/examples/build_system/make/cpu/cortex-m7.mk b/examples/build_system/make/cpu/cortex-m7.mk
new file mode 100644
index 000000000..3e6116179
--- /dev/null
+++ b/examples/build_system/make/cpu/cortex-m7.mk
@@ -0,0 +1,27 @@
+ifeq ($(TOOLCHAIN),gcc)
+ CFLAGS += \
+ -mthumb \
+ -mcpu=cortex-m7 \
+ -mfloat-abi=hard \
+ -mfpu=fpv5-d16 \
+
+else ifeq ($(TOOLCHAIN),clang)
+ CFLAGS += \
+ --target=arm-none-eabi \
+ -mcpu=cortex-m7 \
+ -mfpu=fpv5-d16 \
+
+else ifeq ($(TOOLCHAIN),iar)
+ CFLAGS += \
+ --cpu cortex-m7 \
+ --fpu VFPv5_D16 \
+
+ ASFLAGS += \
+ --cpu cortex-m7 \
+ --fpu VFPv5_D16 \
+
+else
+ $(error "TOOLCHAIN is not supported")
+endif
+
+FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM7/r0p1
diff --git a/examples/build_system/make/cpu/msp430.mk b/examples/build_system/make/cpu/msp430.mk
new file mode 100644
index 000000000..6daa2c38d
--- /dev/null
+++ b/examples/build_system/make/cpu/msp430.mk
@@ -0,0 +1,12 @@
+ifeq ($(TOOLCHAIN),gcc)
+ # nothing to add
+else ifeq ($(TOOLCHAIN),clang)
+ # nothing to add
+else ifeq ($(TOOLCHAIN),iar)
+ # nothing to add
+else
+ $(error "TOOLCHAIN is not supported")
+endif
+
+# For freeRTOS port source
+FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/GCC_MSP430F449
diff --git a/examples/build_system/make/make.mk b/examples/build_system/make/make.mk
new file mode 100644
index 000000000..a78f4130d
--- /dev/null
+++ b/examples/build_system/make/make.mk
@@ -0,0 +1,153 @@
+# ---------------------------------------
+# Common make definition for all examples
+# ---------------------------------------
+
+#-------------------------------------------------------------
+# Toolchain
+# Can be changed via TOOLCHAIN=gcc|iar or CC=arm-none-eabi-gcc|iccarm|clang
+#-------------------------------------------------------------
+
+ifneq (,$(findstring clang,$(CC)))
+ TOOLCHAIN = clang
+else ifneq (,$(findstring iccarm,$(CC)))
+ TOOLCHAIN = iar
+else ifneq (,$(findstring gcc,$(CC)))
+ TOOLCHAIN = gcc
+endif
+
+# Default to GCC
+ifndef TOOLCHAIN
+ TOOLCHAIN = gcc
+endif
+
+#-------------- TOP and CURRENT_PATH ------------
+
+# Set TOP to be the path to get from the current directory (where make was invoked) to the top of the tree.
+# $(lastword $(MAKEFILE_LIST)) returns the name of this makefile relative to where make was invoked.
+THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))
+
+# strip off /examples/build_system/make to get for example ../../..
+# and Set TOP to an absolute path
+TOP = $(abspath $(subst make.mk,../../..,$(THIS_MAKEFILE)))
+
+# Set CURRENT_PATH to the relative path from TOP to the current directory, ie examples/device/cdc_msc_freertos
+CURRENT_PATH = $(subst $(TOP)/,,$(abspath .))
+
+#-------------- Linux/Windows ------------
+
+# Detect whether shell style is windows or not
+# https://stackoverflow.com/questions/714100/os-detecting-makefile/52062069#52062069
+ifeq '$(findstring ;,$(PATH))' ';'
+# PATH contains semicolon - so we're definitely on Windows.
+CMDEXE := 1
+
+# makefile shell commands should use syntax for DOS CMD, not unix sh
+# Force DOS command shell on Windows.
+SHELL := cmd.exe
+endif
+
+ifeq ($(CMDEXE),1)
+ CP = copy
+ RM = del
+ MKDIR = mkdir
+ PYTHON = python
+else
+ CP = cp
+ RM = rm
+ MKDIR = mkdir
+ PYTHON = python3
+endif
+
+
+# Build directory
+BUILD := _build/$(BOARD)
+
+PROJECT := $(notdir $(CURDIR))
+BIN := $(TOP)/_bin/$(BOARD)/$(notdir $(CURDIR))
+
+#-------------- Select the board to build for. ------------
+
+# Board without family
+ifneq ($(wildcard $(TOP)/hw/bsp/$(BOARD)/board.mk),)
+ BOARD_PATH := hw/bsp/$(BOARD)
+ FAMILY :=
+endif
+
+# Board within family
+ifeq ($(BOARD_PATH),)
+ BOARD_PATH := $(subst $(TOP)/,,$(wildcard $(TOP)/hw/bsp/*/boards/$(BOARD)))
+ FAMILY := $(word 3, $(subst /, ,$(BOARD_PATH)))
+ FAMILY_PATH = hw/bsp/$(FAMILY)
+endif
+
+ifeq ($(BOARD_PATH),)
+ $(info You must provide a BOARD parameter with 'BOARD=')
+ $(error Invalid BOARD specified)
+endif
+
+ifeq ($(FAMILY),)
+ include $(TOP)/hw/bsp/$(BOARD)/board.mk
+else
+ # Include Family and Board specific defs
+ include $(TOP)/$(FAMILY_PATH)/family.mk
+ SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FAMILY_PATH)/*.c))
+endif
+
+#-------------- Source files and compiler flags --------------
+# tinyusb makefile
+include $(TOP)/src/tinyusb.mk
+SRC_C += $(TINYUSB_SRC_C)
+
+# Include all source C in family & board folder
+SRC_C += hw/bsp/board.c
+SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(BOARD_PATH)/*.c))
+
+INC += \
+ $(TOP)/$(FAMILY_PATH) \
+ $(TOP)/src \
+
+BOARD_UPPER = $(subst a,A,$(subst b,B,$(subst c,C,$(subst d,D,$(subst e,E,$(subst f,F,$(subst g,G,$(subst h,H,$(subst i,I,$(subst j,J,$(subst k,K,$(subst l,L,$(subst m,M,$(subst n,N,$(subst o,O,$(subst p,P,$(subst q,Q,$(subst r,R,$(subst s,S,$(subst t,T,$(subst u,U,$(subst v,V,$(subst w,W,$(subst x,X,$(subst y,Y,$(subst z,Z,$(subst -,_,$(BOARD))))))))))))))))))))))))))))
+CFLAGS += -DBOARD_$(BOARD_UPPER)
+
+# use max3421 as host controller
+ifeq (${MAX3421_HOST},1)
+ SRC_C += src/portable/analog/max3421/hcd_max3421.c
+ CFLAGS += -DCFG_TUH_MAX3421=1
+ CMAKE_DEFSYM += -DMAX3421_HOST=1
+endif
+
+# Log level is mapped to TUSB DEBUG option
+ifneq ($(LOG),)
+ CMAKE_DEFSYM += -DLOG=$(LOG)
+ CFLAGS += -DCFG_TUSB_DEBUG=$(LOG)
+endif
+
+# Logger: default is uart, can be set to rtt or swo
+ifneq ($(LOGGER),)
+ CMAKE_DEFSYM += -DLOGGER=$(LOGGER)
+endif
+
+ifeq ($(LOGGER),rtt)
+ CFLAGS += -DLOGGER_RTT -DSEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL
+ RTT_SRC = lib/SEGGER_RTT
+ INC += $(TOP)/$(RTT_SRC)/RTT
+ SRC_C += $(RTT_SRC)/RTT/SEGGER_RTT.c
+else ifeq ($(LOGGER),swo)
+ CFLAGS += -DLOGGER_SWO
+endif
+
+# CPU specific flags
+ifdef CPU_CORE
+ include ${TOP}/examples/build_system/make/cpu/$(CPU_CORE).mk
+endif
+
+# toolchain specific
+include ${TOP}/examples/build_system/make/toolchain/arm_$(TOOLCHAIN).mk
+
+# Handy check parameter function
+check_defined = \
+ $(strip $(foreach 1,$1, \
+ $(call __check_defined,$1,$(strip $(value 2)))))
+__check_defined = \
+ $(if $(value $1),, \
+ $(error Undefined make flag: $1$(if $2, ($2))))
diff --git a/examples/rules.mk b/examples/build_system/make/rules.mk
similarity index 50%
rename from examples/rules.mk
rename to examples/build_system/make/rules.mk
index 6a62288ce..7b6b339ed 100644
--- a/examples/rules.mk
+++ b/examples/build_system/make/rules.mk
@@ -7,98 +7,7 @@
# ---------------- GNU Make Start -----------------------
# ESP32-Sx and RP2040 has its own CMake build system
-ifeq (,$(findstring $(FAMILY),esp32s2 esp32s3 rp2040))
-
-# ---------------------------------------
-# Compiler Flags
-# ---------------------------------------
-
-LIBS_GCC ?= -lgcc -lm -lnosys
-
-# libc
-LIBS += $(LIBS_GCC)
-
-ifneq ($(BOARD), spresense)
-LIBS += -lc
-endif
-
-# TinyUSB Stack source
-SRC_C += \
- src/tusb.c \
- src/common/tusb_fifo.c \
- src/device/usbd.c \
- src/device/usbd_control.c \
- src/class/audio/audio_device.c \
- src/class/cdc/cdc_device.c \
- src/class/dfu/dfu_device.c \
- src/class/dfu/dfu_rt_device.c \
- src/class/hid/hid_device.c \
- src/class/midi/midi_device.c \
- src/class/msc/msc_device.c \
- src/class/net/ecm_rndis_device.c \
- src/class/net/ncm_device.c \
- src/class/usbtmc/usbtmc_device.c \
- src/class/video/video_device.c \
- src/class/vendor/vendor_device.c
-
-# TinyUSB stack include
-INC += $(TOP)/src
-
-CFLAGS += $(addprefix -I,$(INC))
-
-ifdef USE_IAR
-
-SRC_S += $(IAR_SRC_S)
-
-ASFLAGS := $(CFLAGS) $(IAR_ASFLAGS) $(ASFLAGS) -S
-IAR_LDFLAGS += --config $(TOP)/$(IAR_LD_FILE)
-CFLAGS += $(IAR_CFLAGS) -e --debug --silent
-
-else
-
-SRC_S += $(GCC_SRC_S)
-
-CFLAGS += $(GCC_CFLAGS) -MD
-
-# LTO makes it difficult to analyze map file for optimizing size purpose
-# We will run this option in ci
-ifeq ($(NO_LTO),1)
-CFLAGS := $(filter-out -flto,$(CFLAGS))
-endif
-
-LDFLAGS += $(CFLAGS) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections
-
-ifdef LD_FILE
-LDFLAGS += -Wl,-T,$(TOP)/$(LD_FILE)
-endif
-
-ifdef GCC_LD_FILE
-LDFLAGS += -Wl,-T,$(TOP)/$(GCC_LD_FILE)
-endif
-
-ifneq ($(SKIP_NANOLIB), 1)
-LDFLAGS += -specs=nosys.specs -specs=nano.specs
-endif
-
-ASFLAGS += $(CFLAGS)
-
-endif # USE_IAR
-
-# Verbose mode
-ifeq ("$(V)","1")
-$(info CFLAGS $(CFLAGS) ) $(info )
-$(info LDFLAGS $(LDFLAGS)) $(info )
-$(info ASFLAGS $(ASFLAGS)) $(info )
-endif
-
-# Assembly files can be name with upper case .S, convert it to .s
-SRC_S := $(SRC_S:.S=.s)
-
-# Due to GCC LTO bug https://bugs.launchpad.net/gcc-arm-embedded/+bug/1747966
-# assembly file should be placed first in linking order
-# '_asm' suffix is added to object of assembly file
-OBJ += $(addprefix $(BUILD)/obj/, $(SRC_S:.s=_asm.o))
-OBJ += $(addprefix $(BUILD)/obj/, $(SRC_C:.c=.o))
+ifeq (,$(findstring $(FAMILY),espressif rp2040))
# ---------------------------------------
# Rules
@@ -108,15 +17,6 @@ all: $(BUILD)/$(PROJECT).bin $(BUILD)/$(PROJECT).hex size
uf2: $(BUILD)/$(PROJECT).uf2
-OBJ_DIRS = $(sort $(dir $(OBJ)))
-$(OBJ): | $(OBJ_DIRS)
-$(OBJ_DIRS):
-ifeq ($(CMDEXE),1)
- @$(MKDIR) $(subst /,\,$@)
-else
- @$(MKDIR) -p $@
-endif
-
# We set vpath to point to the top of the tree so that the source files
# can be located. By following this scheme, it allows a single build rule
# to be used to compile all .c files.
@@ -124,58 +24,33 @@ vpath %.c . $(TOP)
vpath %.s . $(TOP)
vpath %.S . $(TOP)
-# Compile .c file
-$(BUILD)/obj/%.o: %.c
- @echo CC $(notdir $@)
- @$(CC) $(CFLAGS) -c -o $@ $<
+include ${TOP}/examples/build_system/make/toolchain/$(TOOLCHAIN)_rules.mk
-# ASM sources lower case .s
-$(BUILD)/obj/%_asm.o: %.s
- @echo AS $(notdir $@)
- @$(AS) $(ASFLAGS) -c -o $@ $<
+# ---------------------------------------
+# Compiler Flags
+# ---------------------------------------
-# ASM sources upper case .S
-$(BUILD)/obj/%_asm.o: %.S
- @echo AS $(notdir $@)
- @$(AS) $(ASFLAGS) -c -o $@ $<
+CFLAGS += $(addprefix -I,$(INC))
-ifndef USE_IAR
-# GCC based compiler
-$(BUILD)/$(PROJECT).bin: $(BUILD)/$(PROJECT).elf
- @echo CREATE $@
- @$(OBJCOPY) -O binary $^ $@
+# Verbose mode
+ifeq ("$(V)","1")
+$(info CFLAGS $(CFLAGS) ) $(info )
+$(info LDFLAGS $(LDFLAGS)) $(info )
+$(info ASFLAGS $(ASFLAGS)) $(info )
+endif
-$(BUILD)/$(PROJECT).hex: $(BUILD)/$(PROJECT).elf
- @echo CREATE $@
- @$(OBJCOPY) -O ihex $^ $@
-
-$(BUILD)/$(PROJECT).elf: $(OBJ)
- @echo LINK $@
- @$(LD) -o $@ $(LDFLAGS) $^ -Wl,--start-group $(LIBS) -Wl,--end-group
+OBJ_DIRS = $(sort $(dir $(OBJ)))
+$(OBJ): | $(OBJ_DIRS)
+$(OBJ_DIRS):
+ifeq ($(CMDEXE),1)
+ -@$(MKDIR) $(subst /,\,$@)
else
-
-# IAR Compiler
-$(BUILD)/$(PROJECT).bin: $(BUILD)/$(PROJECT).elf
- @echo CREATE $@
- @$(OBJCOPY) --silent --bin $^ $@
-
-$(BUILD)/$(PROJECT).hex: $(BUILD)/$(PROJECT).elf
- @echo CREATE $@
- @$(OBJCOPY) --silent --ihex $^ $@
-
-$(BUILD)/$(PROJECT).elf: $(OBJ)
- @echo LINK $@
- @$(LD) -o $@ $(IAR_LDFLAGS) $^
+ @$(MKDIR) -p $@
endif
# UF2 generation, iMXRT need to strip to text only before conversion
-ifeq ($(FAMILY),imxrt)
-$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).elf
- @echo CREATE $@
- @$(OBJCOPY) -O ihex -R .flash_config -R .ivt $^ $(BUILD)/$(PROJECT)-textonly.hex
- $(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -c -o $@ $(BUILD)/$(PROJECT)-textonly.hex
-else
+ifneq ($(FAMILY),imxrt)
$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).hex
@echo CREATE $@
$(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -c -o $@ $^
@@ -197,10 +72,9 @@ endif
# get depenecies
.PHONY: get-deps
get-deps:
- ifdef DEPS_SUBMODULES
- git -C $(TOP) submodule update --init $(DEPS_SUBMODULES)
- endif
+ $(PYTHON) $(TOP)/tools/get_deps.py ${FAMILY}
+.PHONY: size
size: $(BUILD)/$(PROJECT).elf
-@echo ''
@$(SIZE) $<
@@ -214,7 +88,7 @@ linkermap: $(BUILD)/$(PROJECT).elf
# Flash Targets
# ---------------------------------------
-# Jlink binary
+# --------------- Jlink -----------------
ifeq ($(OS),Windows_NT)
JLINKEXE = JLink.exe
else
@@ -224,20 +98,24 @@ endif
# Jlink Interface
JLINK_IF ?= swd
-# Flash using jlink
-flash-jlink: $(BUILD)/$(PROJECT).hex
- @echo halt > $(BUILD)/$(BOARD).jlink
- @echo r > $(BUILD)/$(BOARD).jlink
- @echo loadfile $^ >> $(BUILD)/$(BOARD).jlink
- @echo r >> $(BUILD)/$(BOARD).jlink
- @echo go >> $(BUILD)/$(BOARD).jlink
- @echo exit >> $(BUILD)/$(BOARD).jlink
- $(JLINKEXE) -device $(JLINK_DEVICE) -if $(JLINK_IF) -JTAGConf -1,-1 -speed auto -CommandFile $(BUILD)/$(BOARD).jlink
+# Jlink script
+$(BUILD)/$(BOARD).jlink: $(BUILD)/$(PROJECT).hex
+ @echo halt > $@
+ @echo loadfile $^ >> $@
+ @echo r >> $@
+ @echo go >> $@
+ @echo exit >> $@
+# Flash using jlink
+flash-jlink: $(BUILD)/$(BOARD).jlink
+ $(JLINKEXE) -device $(JLINK_DEVICE) -if $(JLINK_IF) -JTAGConf -1,-1 -speed auto -CommandFile $<
+
+# --------------- stm32 cube programmer -----------------
# Flash STM32 MCU using stlink with STM32 Cube Programmer CLI
flash-stlink: $(BUILD)/$(PROJECT).elf
STM32_Programmer_CLI --connect port=swd --write $< --go
+# --------------- xfel -----------------
$(BUILD)/$(PROJECT)-sunxi.bin: $(BUILD)/$(PROJECT).bin
$(PYTHON) $(TOP)/tools/mksunxi.py $< $@
@@ -245,18 +123,23 @@ flash-xfel: $(BUILD)/$(PROJECT)-sunxi.bin
xfel spinor write 0 $<
xfel reset
-# Flash using pyocd
+# --------------- pyocd -----------------
PYOCD_OPTION ?=
flash-pyocd: $(BUILD)/$(PROJECT).hex
pyocd flash -t $(PYOCD_TARGET) $(PYOCD_OPTION) $<
#pyocd reset -t $(PYOCD_TARGET)
-# Flash using openocd
+# --------------- openocd -----------------
OPENOCD_OPTION ?=
flash-openocd: $(BUILD)/$(PROJECT).elf
openocd $(OPENOCD_OPTION) -c "program $< verify reset exit"
-# flash with Black Magic Probe
+# --------------- dfu-util -----------------
+DFU_UTIL_OPTION ?= -a 0
+flash-dfu-util: $(BUILD)/$(PROJECT).bin
+ dfu-util -R $(DFU_UTIL_OPTION) -D $<
+
+# --------------- Black Magic -----------------
# This symlink is created by https://github.com/blacksphere/blackmagic/blob/master/driver/99-blackmagic.rules
BMP ?= /dev/ttyBmpGdb
@@ -270,7 +153,11 @@ debug-bmp: $(BUILD)/$(PROJECT).elf
# Create binary directory
$(BIN):
+ifeq ($(CMDEXE),1)
+ @$(MKDIR) $(subst /,\,$@)
+else
@$(MKDIR) -p $@
+endif
# Copy binaries .elf, .bin, .hex, .uf2 to BIN for upload
# due to large size of combined artifacts, only uf2 is uploaded for now
@@ -283,4 +170,4 @@ copy-artifact: $(BIN)
# Print out the value of a make variable.
# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile
print-%:
- @echo $* = $($*)
\ No newline at end of file
+ @echo $* = $($*)
diff --git a/examples/build_system/make/toolchain/arm_clang.mk b/examples/build_system/make/toolchain/arm_clang.mk
new file mode 100644
index 000000000..97face39c
--- /dev/null
+++ b/examples/build_system/make/toolchain/arm_clang.mk
@@ -0,0 +1,10 @@
+CC = clang
+CXX = clang++
+AS = $(CC) -x assembler-with-cpp
+LD = $(CC)
+
+GDB = $(CROSS_COMPILE)gdb
+OBJCOPY = llvm-objcopy
+SIZE = llvm-size
+
+include ${TOP}/examples/build_system/make/toolchain/gcc_common.mk
diff --git a/examples/build_system/make/toolchain/arm_gcc.mk b/examples/build_system/make/toolchain/arm_gcc.mk
new file mode 100644
index 000000000..a8576f8ee
--- /dev/null
+++ b/examples/build_system/make/toolchain/arm_gcc.mk
@@ -0,0 +1,20 @@
+# makefile for arm gcc toolchain
+
+# Can be set by family, default to ARM GCC
+CROSS_COMPILE ?= arm-none-eabi-
+
+CC = $(CROSS_COMPILE)gcc
+CXX = $(CROSS_COMPILE)g++
+AS = $(CC) -x assembler-with-cpp
+LD = $(CC)
+
+GDB = $(CROSS_COMPILE)gdb
+OBJCOPY = $(CROSS_COMPILE)objcopy
+SIZE = $(CROSS_COMPILE)size
+
+CFLAGS += \
+ -fsingle-precision-constant \
+
+LIBS += -lgcc -lm -lnosys
+
+include ${TOP}/examples/build_system/make/toolchain/gcc_common.mk
diff --git a/examples/build_system/make/toolchain/arm_iar.mk b/examples/build_system/make/toolchain/arm_iar.mk
new file mode 100644
index 000000000..17967b41a
--- /dev/null
+++ b/examples/build_system/make/toolchain/arm_iar.mk
@@ -0,0 +1,13 @@
+# makefile for arm iar toolchain
+
+CC = iccarm
+AS = iasmarm
+LD = ilinkarm
+OBJCOPY = ielftool --silent
+SIZE = size
+
+# Enable extension mode (gcc compatible)
+CFLAGS += -e --debug --silent
+
+# silent mode
+ASFLAGS += -S $(addprefix -I,$(INC))
diff --git a/examples/build_system/make/toolchain/clang_rules.mk b/examples/build_system/make/toolchain/clang_rules.mk
new file mode 100644
index 000000000..341f705b1
--- /dev/null
+++ b/examples/build_system/make/toolchain/clang_rules.mk
@@ -0,0 +1 @@
+include ${TOP}/examples/build_system/make/toolchain/gcc_rules.mk
diff --git a/examples/build_system/make/toolchain/gcc_common.mk b/examples/build_system/make/toolchain/gcc_common.mk
new file mode 100644
index 000000000..6986d8bba
--- /dev/null
+++ b/examples/build_system/make/toolchain/gcc_common.mk
@@ -0,0 +1,71 @@
+# ---------------------------------------
+# Compiler Flags
+# ---------------------------------------
+CFLAGS += \
+ -MD \
+ -ggdb \
+ -fdata-sections \
+ -ffunction-sections \
+ -fno-strict-aliasing \
+ -Wall \
+ -Wextra \
+ -Werror \
+ -Wfatal-errors \
+ -Wdouble-promotion \
+ -Wstrict-prototypes \
+ -Wstrict-overflow \
+ -Werror-implicit-function-declaration \
+ -Wfloat-equal \
+ -Wundef \
+ -Wshadow \
+ -Wwrite-strings \
+ -Wsign-compare \
+ -Wmissing-format-attribute \
+ -Wunreachable-code \
+ -Wcast-align \
+ -Wcast-function-type \
+ -Wcast-qual \
+ -Wnull-dereference \
+ -Wuninitialized \
+ -Wunused \
+ -Wreturn-type \
+ -Wredundant-decls \
+
+# conversion is too strict for most mcu driver, may be disable sign/int/arith-conversion
+# -Wconversion
+
+# Size Optimization as default
+CFLAGS_OPTIMIZED ?= -Os
+
+# Debugging/Optimization
+ifeq ($(DEBUG), 1)
+ CFLAGS += -O0
+ NO_LTO = 1
+else
+ CFLAGS += $(CFLAGS_OPTIMIZED)
+endif
+
+# ---------------------------------------
+# Linker Flags
+# ---------------------------------------
+LDFLAGS += \
+ -Wl,-Map=$@.map \
+ -Wl,--cref \
+ -Wl,-gc-sections \
+
+# renesas rx does not support --print-memory-usage flags
+ifneq ($(FAMILY),rx)
+LDFLAGS += -Wl,--print-memory-usage
+endif
+
+ifeq ($(TOOLCHAIN),gcc)
+CC_VERSION := $(shell $(CC) -dumpversion)
+CC_VERSION_MAJOR = $(firstword $(subst ., ,$(CC_VERSION)))
+
+# from version 12
+ifeq ($(strip $(if $(CMDEXE),\
+ $(shell if $(CC_VERSION_MAJOR) geq 12 (echo 1) else (echo 0)),\
+ $(shell expr $(CC_VERSION_MAJOR) \>= 12))), 1)
+LDFLAGS += -Wl,--no-warn-rwx-segment
+endif
+endif
diff --git a/examples/build_system/make/toolchain/gcc_rules.mk b/examples/build_system/make/toolchain/gcc_rules.mk
new file mode 100644
index 000000000..fc5225503
--- /dev/null
+++ b/examples/build_system/make/toolchain/gcc_rules.mk
@@ -0,0 +1,77 @@
+SRC_S += $(SRC_S_GCC)
+
+# Assembly files can be name with upper case .S, convert it to .s
+SRC_S := $(SRC_S:.S=.s)
+
+# Due to GCC LTO bug https://bugs.launchpad.net/gcc-arm-embedded/+bug/1747966
+# assembly file should be placed first in linking order
+# '_asm' suffix is added to object of assembly file
+OBJ += $(addprefix $(BUILD)/obj/, $(SRC_S:.s=_asm.o))
+OBJ += $(addprefix $(BUILD)/obj/, $(SRC_C:.c=.o))
+
+CFLAGS += $(CFLAGS_GCC) -MD
+
+# LTO makes it difficult to analyze map file for optimizing size purpose
+# We will run this option in ci
+ifeq ($(NO_LTO),1)
+CFLAGS := $(filter-out -flto,$(CFLAGS))
+endif
+
+ifneq ($(CFLAGS_SKIP),)
+CFLAGS := $(filter-out $(CFLAGS_SKIP),$(CFLAGS))
+endif
+
+ifeq ($(TOOLCHAIN),clang)
+CFLAGS += $(CFLAGS_CLANG)
+LDFLAGS += $(CFLAGS) $(LDFLAGS_CLANG)
+else
+LDFLAGS += $(CFLAGS) $(LDFLAGS_GCC)
+endif
+
+# TODO should be removed after all examples are updated
+ifdef LD_FILE
+LDFLAGS += -Wl,-T,$(TOP)/$(LD_FILE)
+endif
+
+ifdef LD_FILE_GCC
+LDFLAGS += -Wl,-T,$(TOP)/$(LD_FILE_GCC)
+endif
+
+ASFLAGS += $(CFLAGS)
+
+# libc
+ifneq ($(BOARD), spresense)
+LIBS += -lc
+endif
+
+# ---------------------------------------
+# Rules
+# ---------------------------------------
+
+# Compile .c file
+$(BUILD)/obj/%.o: %.c
+ @echo CC $(notdir $@)
+ @$(CC) $(CFLAGS) -c -o $@ $<
+
+# ASM sources lower case .s
+$(BUILD)/obj/%_asm.o: %.s
+ @echo AS $(notdir $@)
+ @$(AS) $(ASFLAGS) -c -o $@ $<
+
+# ASM sources upper case .S
+$(BUILD)/obj/%_asm.o: %.S
+ @echo AS $(notdir $@)
+ @$(AS) $(ASFLAGS) -c -o $@ $<
+
+OBJCOPY_BIN_OPTION ?=
+$(BUILD)/$(PROJECT).bin: $(BUILD)/$(PROJECT).elf
+ @echo CREATE $@
+ $(OBJCOPY) -O binary $(OBJCOPY_BIN_OPTION) $^ $@
+
+$(BUILD)/$(PROJECT).hex: $(BUILD)/$(PROJECT).elf
+ @echo CREATE $@
+ @$(OBJCOPY) -O ihex $^ $@
+
+$(BUILD)/$(PROJECT).elf: $(OBJ)
+ @echo LINK $@
+ @$(LD) -o $@ $(LDFLAGS) $^ -Wl,--start-group $(LIBS) -Wl,--end-group
diff --git a/examples/build_system/make/toolchain/iar_rules.mk b/examples/build_system/make/toolchain/iar_rules.mk
new file mode 100644
index 000000000..2c066f6da
--- /dev/null
+++ b/examples/build_system/make/toolchain/iar_rules.mk
@@ -0,0 +1,44 @@
+SRC_S += $(SRC_S_IAR)
+
+# Assembly files can be name with upper case .S, convert it to .s
+SRC_S := $(SRC_S:.S=.s)
+
+# Due to GCC LTO bug https://bugs.launchpad.net/gcc-arm-embedded/+bug/1747966
+# assembly file should be placed first in linking order
+# '_asm' suffix is added to object of assembly file
+OBJ += $(addprefix $(BUILD)/obj/, $(SRC_S:.s=_asm.o))
+OBJ += $(addprefix $(BUILD)/obj/, $(SRC_C:.c=.o))
+
+# Linker script
+LDFLAGS += --config $(TOP)/$(LD_FILE_IAR)
+
+# ---------------------------------------
+# Rules
+# ---------------------------------------
+
+# Compile .c file
+$(BUILD)/obj/%.o: %.c
+ @echo CC $(notdir $@)
+ @$(CC) $(CFLAGS) -c -o $@ $<
+
+# ASM sources lower case .s
+$(BUILD)/obj/%_asm.o: %.s
+ @echo AS $(notdir $@)
+ @$(AS) $(ASFLAGS) -c -o $@ $<
+
+# ASM sources upper case .S
+$(BUILD)/obj/%_asm.o: %.S
+ @echo AS $(notdir $@)
+ @$(AS) $(ASFLAGS) -c -o $@ $<
+
+$(BUILD)/$(PROJECT).bin: $(BUILD)/$(PROJECT).elf
+ @echo CREATE $@
+ @$(OBJCOPY) --bin $^ $@
+
+$(BUILD)/$(PROJECT).hex: $(BUILD)/$(PROJECT).elf
+ @echo CREATE $@
+ @$(OBJCOPY) --ihex $^ $@
+
+$(BUILD)/$(PROJECT).elf: $(OBJ)
+ @echo LINK $@
+ @$(LD) -o $@ $(LDFLAGS) $^
diff --git a/examples/device/CMakeLists.txt b/examples/device/CMakeLists.txt
index edf5ab805..c3671da69 100644
--- a/examples/device/CMakeLists.txt
+++ b/examples/device/CMakeLists.txt
@@ -1,20 +1,23 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake)
-project(tinyusb_device_examples)
+project(tinyusb_device_examples C CXX ASM)
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_test_multi_rate)
family_add_subdirectory(board_test)
family_add_subdirectory(cdc_dual_ports)
family_add_subdirectory(cdc_msc)
family_add_subdirectory(cdc_msc_freertos)
+family_add_subdirectory(cdc_uac2)
family_add_subdirectory(dfu)
family_add_subdirectory(dfu_runtime)
family_add_subdirectory(dynamic_configuration)
+family_add_subdirectory(hid_boot_interface)
family_add_subdirectory(hid_composite)
family_add_subdirectory(hid_composite_freertos)
family_add_subdirectory(hid_generic_inout)
@@ -25,4 +28,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 f6e10e2ea..0f5d36193 100644
--- a/examples/device/audio_4_channel_mic/CMakeLists.txt
+++ b/examples/device/audio_4_channel_mic/CMakeLists.txt
@@ -1,28 +1,38 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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/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... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
+# 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 5a455078e..2c825bbf7 100644
--- a/examples/device/audio_4_channel_mic/Makefile
+++ b/examples/device/audio_4_channel_mic/Makefile
@@ -1,12 +1,14 @@
-include ../../../tools/top.mk
-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 ae9b57f1f..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
\ No newline at end of file
+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 a6af5fd19..10e6fe88a 100644
--- a/examples/device/audio_4_channel_mic/src/main.c
+++ b/examples/device/audio_4_channel_mic/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020 Reinhard Panhuber
@@ -34,17 +34,16 @@
#include
#include
#include
+#include
-#include "bsp/board.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);
@@ -84,6 +88,10 @@ int main(void)
// init device stack on configured roothub port
tud_init(BOARD_TUD_RHPORT);
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
// Init values
sampFreq = AUDIO_SAMPLE_RATE;
clkValid = 1;
@@ -93,15 +101,51 @@ 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
led_blinking_task();
audio_task();
}
-
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -132,7 +176,7 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
@@ -141,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
}
//--------------------------------------------------------------------+
@@ -290,7 +347,7 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *
// Those are dummy values for now
ret.bNrChannels = 1;
- ret.bmChannelConfig = 0;
+ ret.bmChannelConfig = (audio_channel_config_t) 0;
ret.iChannelNames = 0;
TU_LOG2(" Get terminal connector\r\n");
@@ -363,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");
@@ -399,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;
}
@@ -415,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 9ab15135d..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,10 +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()
-
\ No newline at end of file
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/src/usb_descriptors.c b/examples/device/audio_4_channel_mic/src/usb_descriptors.c
index 8929f3057..728a5f9ce 100644
--- a/examples/device/audio_4_channel_mic/src/usb_descriptors.c
+++ b/examples/device/audio_4_channel_mic/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,6 +23,7 @@
*
*/
+#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.
@@ -44,7 +45,7 @@ tusb_desc_device_t const desc_device =
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0200,
- // Use Interface Association Descriptor (IAD) for CDC
+ // 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,
@@ -96,7 +97,7 @@ enum
uint8_t const desc_configuration[] =
{
- // Interface count, string index, total length, attribute, power in mA
+ // 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
@@ -116,50 +117,63 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// String Descriptors
//--------------------------------------------------------------------+
-// 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
- "123458", // 3: Serials, should use chip ID
- "UAC2", // 4: Audio Interface
+// String Descriptor Index
+enum {
+ STRID_LANGID = 0,
+ STRID_MANUFACTURER,
+ STRID_PRODUCT,
+ STRID_SERIAL,
};
-static uint16_t _desc_str[32];
+// 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)
-{
+uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
(void) langid;
+ size_t chr_count;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // Convert ASCII string into UTF-16
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/audio_test/CMakeLists.txt b/examples/device/audio_test/CMakeLists.txt
index cb321f9a8..f61e1b640 100644
--- a/examples/device/audio_test/CMakeLists.txt
+++ b/examples/device/audio_test/CMakeLists.txt
@@ -1,28 +1,33 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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/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... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+# 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_test/Makefile b/examples/device/audio_test/Makefile
index 5a455078e..7fa475da5 100644
--- a/examples/device/audio_test/Makefile
+++ b/examples/device/audio_test/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -9,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 ae9b57f1f..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
\ No newline at end of file
+mcu:SAMG
+family:espressif
diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c
index d0849c7ac..06783ccfb 100644
--- a/examples/device/audio_test/src/main.c
+++ b/examples/device/audio_test/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020 Reinhard Panhuber
@@ -35,7 +35,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
@@ -71,7 +71,7 @@ audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1];
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];
+uint16_t test_buffer_audio[(CFG_TUD_AUDIO_EP_SZ_IN - 2) / 2];
uint16_t startVal = 0;
void led_blinking_task(void);
@@ -85,6 +85,10 @@ int main(void)
// init device stack on configured roothub port
tud_init(BOARD_TUD_RHPORT);
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
// Init values
sampFreq = AUDIO_SAMPLE_RATE;
clkValid = 1;
@@ -100,9 +104,6 @@ int main(void)
led_blinking_task();
audio_task();
}
-
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -133,7 +134,7 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
@@ -291,7 +292,7 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *
// Those are dummy values for now
ret.bNrChannels = 1;
- ret.bmChannelConfig = 0;
+ ret.bmChannelConfig = (audio_channel_config_t) 0;
ret.iChannelNames = 0;
TU_LOG2(" Get terminal connector\r\n");
@@ -400,7 +401,7 @@ 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;
- tud_audio_write ((uint8_t *)test_buffer_audio, CFG_TUD_AUDIO_EP_SZ_IN);
+ tud_audio_write ((uint8_t *)test_buffer_audio, CFG_TUD_AUDIO_EP_SZ_IN - 2);
return true;
}
@@ -413,7 +414,7 @@ bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uin
(void) ep_in;
(void) cur_alt_setting;
- for (size_t cnt = 0; cnt < CFG_TUD_AUDIO_EP_SZ_IN/2; cnt++)
+ for (size_t cnt = 0; cnt < (CFG_TUD_AUDIO_EP_SZ_IN - 2) / 2; cnt++)
{
test_buffer_audio[cnt] = startVal++;
}
diff --git a/examples/device/audio_test/src/plot_audio_samples.py b/examples/device/audio_test/src/plot_audio_samples.py
index 6e3c4978e..1504684a6 100644
--- a/examples/device/audio_test/src/plot_audio_samples.py
+++ b/examples/device/audio_test/src/plot_audio_samples.py
@@ -2,6 +2,7 @@ import sounddevice as sd
import matplotlib.pyplot as plt
import numpy as np
import platform
+import csv
if __name__ == '__main__':
@@ -31,4 +32,6 @@ if __name__ == '__main__':
plt.ylabel('Amplitude')
plt.title('MicNode')
plt.show()
-
\ No newline at end of file
+
+ samples = np.array(myrecording)
+ np.savetxt('Output.csv', samples, delimiter=",", fmt='%s')
diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h
index 355ed1011..9f38612a9 100644
--- a/examples/device/audio_test/src/tusb_config.h
+++ b/examples/device/audio_test/src/tusb_config.h
@@ -114,7 +114,7 @@ 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 * 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 1 Channel
+#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
diff --git a/examples/device/audio_test/src/usb_descriptors.c b/examples/device/audio_test/src/usb_descriptors.c
index da3e203d7..9864377f6 100644
--- a/examples/device/audio_test/src/usb_descriptors.c
+++ b/examples/device/audio_test/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,6 +23,7 @@
*
*/
+#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.
@@ -44,7 +45,7 @@ tusb_desc_device_t const desc_device =
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0200,
- // Use Interface Association Descriptor (IAD) for CDC
+ // 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,
@@ -96,7 +97,7 @@ enum
uint8_t const desc_configuration[] =
{
- // Interface count, string index, total length, attribute, power in mA
+ // 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
@@ -116,50 +117,65 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// 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
- "123456", // 3: Serials, should use chip ID
- "UAC2", // 4: Audio Interface
+ (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];
+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;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // Convert ASCII string into UTF-16
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- for(uint8_t i=0; i 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));
+ _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/CMakeLists.txt b/examples/device/audio_test_multi_rate/CMakeLists.txt
new file mode 100644
index 000000000..f61e1b640
--- /dev/null
+++ b/examples/device/audio_test_multi_rate/CMakeLists.txt
@@ -0,0 +1,33 @@
+cmake_minimum_required(VERSION 3.17)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
+
+# gets PROJECT name for the example (e.g. -)
+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/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/audio_test_multi_rate/Makefile b/examples/device/audio_test_multi_rate/Makefile
new file mode 100644
index 000000000..7fa475da5
--- /dev/null
+++ b/examples/device/audio_test_multi_rate/Makefile
@@ -0,0 +1,11 @@
+include ../../build_system/make/make.mk
+
+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/audio_test_multi_rate/skip.txt b/examples/device/audio_test_multi_rate/skip.txt
new file mode 100644
index 000000000..65b137814
--- /dev/null
+++ b/examples/device/audio_test_multi_rate/skip.txt
@@ -0,0 +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
new file mode 100644
index 000000000..2ff7f10bd
--- /dev/null
+++ b/examples/device/audio_test_multi_rate/src/main.c
@@ -0,0 +1,525 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Reinhard Panhuber
+ * Copyright (c) 2022 HiFiPhile
+ *
+ * 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
+#include
+#include
+
+#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;
+
+// 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 bytesPerSample;
+uint8_t clkValid;
+
+// Range states
+// List of supported sample rates
+static const uint32_t sampleRatesList[] =
+{
+ 32000, 48000, 96000
+};
+
+#define N_sampleRates TU_ARRAY_SIZE(sampleRatesList)
+
+// Bytes per format of every Alt settings
+static const uint8_t bytesPerSampleAltList[CFG_TUD_AUDIO_FUNC_1_N_FORMATS] =
+{
+ CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX,
+ CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX,
+};
+
+audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state
+
+
+// Audio test data
+CFG_TUSB_MEM_ALIGN uint8_t test_buffer_audio[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX];
+uint16_t startVal = 0;
+
+void led_blinking_task(void);
+void audio_task(void);
+
+/*------------- MAIN -------------*/
+int main(void)
+{
+ board_init();
+
+ // init device stack on configured roothub port
+ tud_init(BOARD_TUD_RHPORT);
+
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
+ // Init values
+ sampFreq = sampleRatesList[0];
+ clkValid = 1;
+
+ while (1)
+ {
+ tud_task(); // tinyusb device task
+ led_blinking_task();
+ audio_task();
+ }
+
+
+ return 0;
+}
+
+//--------------------------------------------------------------------+
+// 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 set interface is called, typically on start/stop streaming or format change
+bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request)
+{
+ (void)rhport;
+ //uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex));
+ uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue));
+
+ // Clear buffer when streaming format is changed
+ if(alt != 0)
+ {
+ bytesPerSample = bytesPerSampleAltList[alt-1];
+ }
+ return true;
+}
+
+// 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 == UAC2_ENTITY_FEATURE_UNIT )
+ {
+ 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;
+ }
+ }
+
+ // Clock Source unit
+ if ( entityID == UAC2_ENTITY_CLOCK )
+ {
+ switch ( ctrlSel )
+ {
+ case AUDIO_CS_CTRL_SAM_FREQ:
+ TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_4_t));
+
+ sampFreq = (uint32_t)((audio_control_cur_4_t *)pBuff)->bCur;
+
+ TU_LOG2("Clock set current freq: %" PRIu32 "\r\n", sampFreq);
+
+ return true;
+ break;
+
+ // 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 tud_control_xfer(rhport, p_request, &tmp, 1);
+
+ 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 == UAC2_ENTITY_INPUT_TERMINAL)
+ {
+ 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 == UAC2_ENTITY_FEATURE_UNIT)
+ {
+ 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 = 30; // +30 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 == UAC2_ENTITY_CLOCK )
+ {
+ 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");
+ audio_control_range_4_n_t(N_sampleRates) rangef =
+ {
+ .wNumSubRanges = tu_htole16(N_sampleRates)
+ };
+ TU_LOG1("Clock get %d freq ranges\r\n", N_sampleRates);
+ for(uint8_t i = 0; i < N_sampleRates; i++)
+ {
+ rangef.subrange[i].bMin = (int32_t)sampleRatesList[i];
+ rangef.subrange[i].bMax = (int32_t)sampleRatesList[i];
+ rangef.subrange[i].bRes = 0;
+ TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int)rangef.subrange[i].bMin, (int)rangef.subrange[i].bMax, (int)rangef.subrange[i].bRes);
+ }
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &rangef, sizeof(rangef));
+ }
+ // 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, (uint16_t)(sampFreq / (TUD_OPT_HIGH_SPEED ? 8000 : 1000) * bytesPerSample));
+
+ 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;
+
+ // 16bit
+ if(bytesPerSample == 2)
+ {
+ uint16_t* pData_16 = (uint16_t*)((void*)test_buffer_audio);
+ for (size_t cnt = 0; cnt < sampFreq / (TUD_OPT_HIGH_SPEED ? 8000 : 1000); cnt++)
+ {
+ pData_16[cnt] = startVal++;
+ }
+ }
+ // 24bit in 32bit slot
+ else if(bytesPerSample == 4)
+ {
+ uint32_t* pData_32 = (uint32_t*)((void*)test_buffer_audio);
+ for (size_t cnt = 0; cnt < sampFreq / (TUD_OPT_HIGH_SPEED ? 8000 : 1000); cnt++)
+ {
+ pData_32[cnt] = (uint32_t)startVal++ << 16U;
+ }
+ }
+
+ 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)
+{
+ 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/audio_test_multi_rate/src/plot_audio_samples.py b/examples/device/audio_test_multi_rate/src/plot_audio_samples.py
new file mode 100644
index 000000000..c92e49957
--- /dev/null
+++ b/examples/device/audio_test_multi_rate/src/plot_audio_samples.py
@@ -0,0 +1,37 @@
+import sounddevice as sd
+import matplotlib.pyplot as plt
+import numpy as np
+import platform
+import csv
+
+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 = 96000 # Sample rate
+ duration = 100e-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()
+
+ samples = np.array(myrecording)
+ np.savetxt('Output.csv', samples, delimiter=",", fmt='%s')
diff --git a/examples/device/audio_test_multi_rate/src/tusb_config.h b/examples/device/audio_test_multi_rate/src/tusb_config.h
new file mode 100644
index 000000000..1c8288bce
--- /dev/null
+++ b/examples/device/audio_test_multi_rate/src/tusb_config.h
@@ -0,0 +1,141 @@
+/*
+ * 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
+
+#include "usb_descriptors.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
+#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
+
+#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
+//--------------------------------------------------------------------
+
+#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 96000
+
+// How many formats are used, need to adjust USB descriptor if changed
+#define CFG_TUD_AUDIO_FUNC_1_N_FORMATS 2
+
+// 16bit in 16bit slots
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX 2
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX 16
+
+// 24bit in 32bit slots
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX 4
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX 24
+
+// Have a look into audio_device.h for all configurations
+
+#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_ONE_CH_2_FORMAT_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_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_FUNC_1_FORMAT_1_EP_SZ_IN 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)
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN 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)
+
+#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_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_FUNC_1_EP_IN_SZ_MAX
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TUSB_CONFIG_H_ */
diff --git a/examples/device/audio_test_multi_rate/src/usb_descriptors.c b/examples/device/audio_test_multi_rate/src/usb_descriptors.c
new file mode 100644
index 000000000..f50e70a25
--- /dev/null
+++ b/examples/device/audio_test_multi_rate/src/usb_descriptors.c
@@ -0,0 +1,185 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ * Copyright (c) 2022 HiFiPhile
+ *
+ * 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] 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_2_FORMAT_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_2_FORMAT_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_epin*/ 0x80 | EPNUM_AUDIO)
+};
+
+TU_VERIFY_STATIC(sizeof(desc_configuration) == CONFIG_TOTAL_LEN, "Incorrect size");
+
+// 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/src/usb_descriptors.h b/examples/device/audio_test_multi_rate/src/usb_descriptors.h
new file mode 100644
index 000000000..8381e31f5
--- /dev/null
+++ b/examples/device/audio_test_multi_rate/src/usb_descriptors.h
@@ -0,0 +1,102 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 HiFiPhile
+ *
+ * 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_
+
+// #include "tusb.h"
+
+// Unit numbers are arbitrary selected
+#define UAC2_ENTITY_CLOCK 0x04
+#define UAC2_ENTITY_INPUT_TERMINAL 0x01
+#define UAC2_ENTITY_OUTPUT_TERMINAL 0x03
+#define UAC2_ENTITY_FEATURE_UNIT 0x02
+
+
+#define TUD_AUDIO_MIC_ONE_CH_2_FORMAT_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\
+ + TUD_AUDIO_DESC_STD_AC_LEN\
+ + TUD_AUDIO_DESC_CS_AC_LEN\
+ + TUD_AUDIO_DESC_CLK_SRC_LEN\
+ + TUD_AUDIO_DESC_INPUT_TERM_LEN\
+ + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\
+ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\
+ /* Interface 1, Alternate 0 */\
+ + TUD_AUDIO_DESC_STD_AS_INT_LEN\
+ /* Interface 1, Alternate 1 */\
+ + TUD_AUDIO_DESC_STD_AS_INT_LEN\
+ + TUD_AUDIO_DESC_CS_AS_INT_LEN\
+ + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\
+ + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\
+ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\
+ /* Interface 1, Alternate 2 */\
+ + TUD_AUDIO_DESC_STD_AS_INT_LEN\
+ + TUD_AUDIO_DESC_CS_AS_INT_LEN\
+ + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\
+ + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\
+ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN)
+
+
+#define TUD_AUDIO_MIC_ONE_CH_2_FORMAT_DESCRIPTOR(_itfnum, _stridx, _epin) \
+ /* Standard Interface Association Descriptor (IAD) */\
+ TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\
+ /* Standard AC Interface Descriptor(4.7.1) */\
+ TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\
+ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\
+ TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\
+ /* Clock Source Descriptor(4.7.2.1) */\
+ TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK, /*_ctrl*/ AUDIO_CTRL_RW << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS | AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS, /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\
+ /* Input Terminal Descriptor(4.7.2.4) */\
+ TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 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_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ UAC2_ENTITY_INPUT_TERMINAL, /*_srcid*/ UAC2_ENTITY_FEATURE_UNIT, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\
+ /* Feature Unit Descriptor(4.7.2.8) */\
+ TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ UAC2_ENTITY_FEATURE_UNIT, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\
+ /* 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)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\
+ /* Standard AS Interface Descriptor(4.9.1) */\
+ /* Interface 1, Alternate 1 - alternate interface for data streaming */\
+ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\
+ /* Class-Specific AS Interface Descriptor(4.9.2) */\
+ TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
+ /* 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_RX),\
+ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
+ TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, /*_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 1, Alternate 2 - alternate interface for data streaming */\
+ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\
+ /* Class-Specific AS Interface Descriptor(4.9.2) */\
+ TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
+ /* 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_RX),\
+ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
+ TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN, /*_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)
+
+
+#endif
diff --git a/examples/device/board_test/CMakeLists.txt b/examples/device/board_test/CMakeLists.txt
index 37113578e..012eff095 100644
--- a/examples/device/board_test/CMakeLists.txt
+++ b/examples/device/board_test/CMakeLists.txt
@@ -1,42 +1,32 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
-# Check for -DFAMILY=
-if(FAMILY MATCHES "^esp32s[2-3]")
- # use BOARD-Directory name for project id
- get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
- set(PROJECT ${BOARD}-${PROJECT})
+# gets PROJECT name for the example (e.g. -)
+family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
- # TOP is absolute path to root directory of TinyUSB git repo
- set(TOP "../../..")
- get_filename_component(TOP "${TOP}" REALPATH)
+project(${PROJECT} C CXX ASM)
- project(${PROJECT})
+# Checks this example is valid for the family and initializes the project
+family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
-else()
-
- # gets PROJECT name for the example (e.g. -)
- family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-
- project(${PROJECT})
-
- # Checks this example is valid for the family and initializes the project
- family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
-
- add_executable(${PROJECT})
-
- # Example source
- target_sources(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
- )
-
- # Example include
- target_include_directories(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src
- )
-
- # Configure compilation flags and libraries for the example... see the corresponding function
- # in hw/bsp/FAMILY/family.cmake for details.
- family_configure_device_example(${PROJECT})
+# 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/main.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/board_test/Makefile b/examples/device/board_test/Makefile
index 5a455078e..7fa475da5 100644
--- a/examples/device/board_test/Makefile
+++ b/examples/device/board_test/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -9,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/CMakeLists.txt b/examples/device/board_test/src/CMakeLists.txt
index e4e1f4e9a..8d85dcafd 100644
--- a/examples/device/board_test/src/CMakeLists.txt
+++ b/examples/device/board_test/src/CMakeLists.txt
@@ -1,17 +1,3 @@
-# FAMILY = esp32sx
idf_component_register(SRCS "main.c"
INCLUDE_DIRS "."
- REQUIRES freertos soc)
-
-file(TO_NATIVE_PATH "${TOP}/hw/bsp/${FAMILY}/boards/${BOARD}/board.cmake" board_cmake)
-
-if(EXISTS ${board_cmake})
- include(${board_cmake})
-endif()
-
-idf_component_get_property( FREERTOS_ORIG_INCLUDE_PATH freertos ORIG_INCLUDE_PATH)
-target_include_directories(${COMPONENT_TARGET} PUBLIC
- "${FREERTOS_ORIG_INCLUDE_PATH}"
- "${TOP}/hw"
- "${TOP}/src"
-)
+ REQUIRES boards tinyusb_src)
diff --git a/examples/device/board_test/src/main.c b/examples/device/board_test/src/main.c
index 0289ca15f..91799eb89 100644
--- a/examples/device/board_test/src/main.c
+++ b/examples/device/board_test/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -26,39 +26,31 @@
#include
#include
#include
-
-#include "bsp/board.h"
-
-//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF PROTYPES
-//--------------------------------------------------------------------+
+#include "bsp/board_api.h"
/* 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,18 +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);
}
}
-
- return 0;
}
#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/CMakeLists.txt b/examples/device/cdc_dual_ports/CMakeLists.txt
index abc4d91da..f61e1b640 100644
--- a/examples/device/cdc_dual_ports/CMakeLists.txt
+++ b/examples/device/cdc_dual_ports/CMakeLists.txt
@@ -1,28 +1,33 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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/main.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.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
- )
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ )
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+# 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/cdc_dual_ports/Makefile b/examples/device/cdc_dual_ports/Makefile
index 5a455078e..7fa475da5 100644
--- a/examples/device/cdc_dual_ports/Makefile
+++ b/examples/device/cdc_dual_ports/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -9,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 0264f0566..1167a5d50 100644
--- a/examples/device/cdc_dual_ports/src/main.c
+++ b/examples/device/cdc_dual_ports/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -28,44 +28,53 @@
#include
#include
-#include "bsp/board.h"
+#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
tud_init(BOARD_TUD_RHPORT);
- while (1)
- {
- tud_task(); // tinyusb device task
- cdc_task();
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
}
- return 0;
+ 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 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/cdc_msc/CMakeLists.txt b/examples/device/cdc_msc/CMakeLists.txt
index fa6e83b7e..9415f8c68 100644
--- a/examples/device/cdc_msc/CMakeLists.txt
+++ b/examples/device/cdc_msc/CMakeLists.txt
@@ -1,29 +1,35 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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/main.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_disk.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
- )
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_disk.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
+ )
# Example include
target_include_directories(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src
- )
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ )
# Configure compilation flags and libraries for the example... see the corresponding function
# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+family_configure_device_example(${PROJECT} noos)
diff --git a/examples/device/cdc_msc/Makefile b/examples/device/cdc_msc/Makefile
index 69b633fea..0c2e37180 100644
--- a/examples/device/cdc_msc/Makefile
+++ b/examples/device/cdc_msc/Makefile
@@ -1,12 +1,15 @@
-include ../../../tools/top.mk
-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/msc_disk.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/cdc_msc/skip.txt b/examples/device/cdc_msc/skip.txt
index d844feae8..833fd072c 100644
--- a/examples/device/cdc_msc/skip.txt
+++ b/examples/device/cdc_msc/skip.txt
@@ -1 +1,2 @@
-mcu:SAMD11
\ No newline at end of file
+mcu:SAMD11
+family:espressif
diff --git a/examples/device/cdc_msc/src/main.c b/examples/device/cdc_msc/src/main.c
index c83299e59..4581a3bab 100644
--- a/examples/device/cdc_msc/src/main.c
+++ b/examples/device/cdc_msc/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,11 +23,7 @@
*
*/
-#include
-#include
-#include
-
-#include "bsp/board.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,22 +47,22 @@ 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
tud_init(BOARD_TUD_RHPORT);
- while (1)
- {
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
+ while (1) {
tud_task(); // tinyusb device task
led_blinking_task();
cdc_task();
}
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -74,45 +70,39 @@ 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)
-{
- blink_interval_ms = BLINK_MOUNTED;
+void tud_resume_cb(void) {
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
// 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));
@@ -129,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/src/msc_disk.c b/examples/device/cdc_msc/src/msc_disk.c
index e67e381ce..d2f8628f1 100644
--- a/examples/device/cdc_msc/src/msc_disk.c
+++ b/examples/device/cdc_msc/src/msc_disk.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,7 +23,7 @@
*
*/
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
#if CFG_TUD_MSC
diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c
index 6b59ed50f..2afa24903 100644
--- a/examples/device/cdc_msc/src/usb_descriptors.c
+++ b/examples/device/cdc_msc/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,6 +23,7 @@
*
*/
+#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.
@@ -41,35 +42,33 @@
//--------------------------------------------------------------------+
// Device Descriptors
//--------------------------------------------------------------------+
-tusb_desc_device_t const desc_device =
-{
- .bLength = sizeof(tusb_desc_device_t),
- .bDescriptorType = TUSB_DESC_DEVICE,
- .bcdUSB = USB_BCD,
+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 CDC
- // 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,
+ // Use Interface Association Descriptor (IAD) for CDC
+ // 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,
+ .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
- .idVendor = USB_VID,
- .idProduct = USB_PID,
- .bcdDevice = 0x0100,
+ .idVendor = USB_VID,
+ .idProduct = USB_PID,
+ .bcdDevice = 0x0100,
- .iManufacturer = 0x01,
- .iProduct = 0x02,
- .iSerialNumber = 0x03,
+ .iManufacturer = 0x01,
+ .iProduct = 0x02,
+ .iSerialNumber = 0x03,
- .bNumConfigurations = 0x01
+ .bNumConfigurations = 0x01
};
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
-uint8_t const * tud_descriptor_device_cb(void)
-{
+uint8_t const *tud_descriptor_device_cb(void) {
return (uint8_t const *) &desc_device;
}
@@ -77,8 +76,7 @@ uint8_t const * tud_descriptor_device_cb(void)
// Configuration Descriptor
//--------------------------------------------------------------------+
-enum
-{
+enum {
ITF_NUM_CDC = 0,
ITF_NUM_CDC_DATA,
ITF_NUM_MSC,
@@ -95,7 +93,7 @@ enum
#define EPNUM_MSC_OUT 0x05
#define EPNUM_MSC_IN 0x85
-#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
+#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_CDC_NOTIF 0x81
@@ -140,67 +138,62 @@ enum
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN)
// full speed configuration
-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, 0x00, 100),
+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, 0x00, 100),
- // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
- TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
+ // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
+ TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
- // Interface number, string index, EP Out & EP In address, EP size
- TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64),
+ // Interface number, string index, EP Out & EP In address, EP size
+ TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64),
};
#if TUD_OPT_HIGH_SPEED
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
// high speed configuration
-uint8_t const desc_hs_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),
+uint8_t const desc_hs_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 notification address and size, EP data address (out, in) and size.
- TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
+ // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
+ TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
- // Interface number, string index, EP Out & EP In address, EP size
- TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512),
+ // Interface number, string index, EP Out & EP In address, EP size
+ TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512),
};
// other speed configuration
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
// 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_qualifier_t),
- .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
- .bcdUSB = USB_BCD,
+tusb_desc_device_qualifier_t const desc_device_qualifier = {
+ .bLength = sizeof(tusb_desc_device_qualifier_t),
+ .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
+ .bcdUSB = USB_BCD,
- .bDeviceClass = TUSB_CLASS_MISC,
- .bDeviceSubClass = MISC_SUBCLASS_COMMON,
- .bDeviceProtocol = MISC_PROTOCOL_IAD,
+ .bDeviceClass = TUSB_CLASS_MISC,
+ .bDeviceSubClass = MISC_SUBCLASS_COMMON,
+ .bDeviceProtocol = MISC_PROTOCOL_IAD,
- .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
- .bNumConfigurations = 0x01,
- .bReserved = 0x00
+ .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;
+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)
-{
+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
@@ -220,13 +213,12 @@ uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
// 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
#if TUD_OPT_HIGH_SPEED
// Although we are highspeed, host may be fullspeed.
- return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
+ return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
#else
return desc_fs_configuration;
#endif
@@ -236,53 +228,64 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// String Descriptors
//--------------------------------------------------------------------+
-// 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
- "123456789012", // 3: Serials, should use chip ID
- "TinyUSB CDC", // 4: CDC Interface
- "TinyUSB MSC", // 5: MSC Interface
+// String Descriptor Index
+enum {
+ STRID_LANGID = 0,
+ STRID_MANUFACTURER,
+ STRID_PRODUCT,
+ STRID_SERIAL,
};
-static uint16_t _desc_str[32];
+// 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 CDC", // 4: CDC Interface
+ "TinyUSB MSC", // 5: MSC 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;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // 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
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/cdc_msc_freertos/CMakeLists.txt b/examples/device/cdc_msc_freertos/CMakeLists.txt
index cbd75efd6..33c7a1ec0 100644
--- a/examples/device/cdc_msc_freertos/CMakeLists.txt
+++ b/examples/device/cdc_msc_freertos/CMakeLists.txt
@@ -1,22 +1,35 @@
-cmake_minimum_required(VERSION 3.5)
-
-# TOP is absolute path to root directory of TinyUSB git repo
-# needed for esp32sx build. TODO could be removed later on
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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})
-# Check for -DFAMILY=
-if(FAMILY MATCHES "^esp32s[2-3]")
-else()
- message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
+# 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/msc_disk.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/cdc_msc_freertos/Makefile b/examples/device/cdc_msc_freertos/Makefile
index 4ee816880..fe3fb6482 100644
--- a/examples/device/cdc_msc_freertos/Makefile
+++ b/examples/device/cdc_msc_freertos/Makefile
@@ -1,18 +1,15 @@
-DEPS_SUBMODULES += lib/FreeRTOS-Kernel
-
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
FREERTOS_SRC = lib/FreeRTOS-Kernel
-FREERTOS_PORTABLE_SRC= $(FREERTOS_SRC)/portable/$(if $(USE_IAR),IAR,GCC)/$(FREERTOS_PORT)
+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 = \
src/freertos_hook.c \
@@ -28,22 +25,22 @@ SRC_C += \
$(FREERTOS_SRC)/queue.c \
$(FREERTOS_SRC)/tasks.c \
$(FREERTOS_SRC)/timers.c \
- $(subst ../../../,,$(wildcard ../../../$(FREERTOS_PORTABLE_SRC)/*.c))
+ $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.c))
SRC_S += \
- $(subst ../../../,,$(wildcard ../../../$(FREERTOS_PORTABLE_SRC)/*.s))
+ $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.s))
# include heap manage if configSUPPORT_DYNAMIC_ALLOCATION = 1
# SRC_C += $(FREERTOS_SRC)/portable/MemMang/heap_1.c
# CFLAGS += -Wno-error=sign-compare
# Suppress FreeRTOSConfig.h warnings
-GCC_CFLAGS += -Wno-error=redundant-decls
+CFLAGS_GCC += -Wno-error=redundant-decls
# Suppress FreeRTOS source warnings
-GCC_CFLAGS += -Wno-error=cast-qual
+CFLAGS_GCC += -Wno-error=cast-qual
# FreeRTOS (lto + Os) linker issue
-LDFLAGS += -Wl,--undefined=vTaskSwitchContext
+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 49b8ee57b..a6f96b288 100644
--- a/examples/device/cdc_msc_freertos/skip.txt
+++ b/examples/device/cdc_msc_freertos/skip.txt
@@ -8,5 +8,6 @@ mcu:RP2040
mcu:SAMD11
mcu:SAMX7X
mcu:VALENTYUSB_EPTRI
+mcu:RAXXX
family:broadcom_32bit
family:broadcom_64bit
diff --git a/examples/device/cdc_msc_freertos/src/CMakeLists.txt b/examples/device/cdc_msc_freertos/src/CMakeLists.txt
index 9216e2b49..fee264363 100644
--- a/examples/device/cdc_msc_freertos/src/CMakeLists.txt
+++ b/examples/device/cdc_msc_freertos/src/CMakeLists.txt
@@ -1,35 +1,4 @@
+# This file is for ESP-IDF only
idf_component_register(SRCS "main.c" "usb_descriptors.c" "msc_disk.c"
INCLUDE_DIRS "."
- REQUIRES freertos soc)
-
-file(TO_NATIVE_PATH "${TOP}/hw/bsp/${FAMILY}/boards/${BOARD}/board.cmake" board_cmake)
-
-if(EXISTS ${board_cmake})
- include(${board_cmake})
-endif()
-
-target_include_directories(${COMPONENT_TARGET} PUBLIC
- "${TOP}/hw"
- "${TOP}/src"
-)
-
-target_compile_definitions(${COMPONENT_TARGET} PUBLIC
- ESP_PLATFORM
-)
-
-target_sources(${COMPONENT_TARGET} PUBLIC
- "${TOP}/src/tusb.c"
- "${TOP}/src/common/tusb_fifo.c"
- "${TOP}/src/device/usbd.c"
- "${TOP}/src/device/usbd_control.c"
- "${TOP}/src/class/cdc/cdc_device.c"
- "${TOP}/src/class/dfu/dfu_rt_device.c"
- "${TOP}/src/class/hid/hid_device.c"
- "${TOP}/src/class/midi/midi_device.c"
- "${TOP}/src/class/msc/msc_device.c"
- "${TOP}/src/class/net/ecm_rndis_device.c"
- "${TOP}/src/class/net/ncm_device.c"
- "${TOP}/src/class/usbtmc/usbtmc_device.c"
- "${TOP}/src/class/vendor/vendor_device.c"
- "${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c"
-)
+ REQUIRES boards tinyusb_src)
diff --git a/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
index 9bef9bbbf..6cc7a6577 100644
--- a/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
+++ b/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
@@ -81,7 +81,7 @@
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
-#define configQUEUE_REGISTRY_SIZE 2
+#define configQUEUE_REGISTRY_SIZE 4
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
@@ -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 cfb14aa2b..607d40270 100644
--- a/examples/device/cdc_msc_freertos/src/main.c
+++ b/examples/device/cdc_msc_freertos/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -27,10 +27,10 @@
#include
#include
-#include "bsp/board.h"
+#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
@@ -136,9 +134,12 @@ void usb_device_task(void* param)
// 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)
- {
+ while (1) {
// put this thread to waiting state until there is new events
tud_task();
@@ -152,49 +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)
-{
- xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_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
@@ -217,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 a895f4738..c8a04bb74 100644
--- a/examples/device/cdc_msc_freertos/src/msc_disk.c
+++ b/examples/device/cdc_msc_freertos/src/msc_disk.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,7 +23,7 @@
*
*/
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
#if CFG_TUD_MSC
@@ -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 0ec8896b9..e743c9148 100644
--- a/examples/device/cdc_msc_freertos/src/tusb_config.h
+++ b/examples/device/cdc_msc_freertos/src/tusb_config.h
@@ -54,10 +54,12 @@
#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 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_msc_freertos/src/usb_descriptors.c b/examples/device/cdc_msc_freertos/src/usb_descriptors.c
index 30a712275..9c29701c7 100644
--- a/examples/device/cdc_msc_freertos/src/usb_descriptors.c
+++ b/examples/device/cdc_msc_freertos/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,6 +23,7 @@
*
*/
+#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.
@@ -212,53 +213,65 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
- "123456789012", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
"TinyUSB CDC", // 4: CDC Interface
"TinyUSB MSC", // 5: MSC Interface
};
-static uint16_t _desc_str[32];
+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;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // 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
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/cdc_uac2/CMakeLists.txt b/examples/device/cdc_uac2/CMakeLists.txt
new file mode 100644
index 000000000..64e4374e9
--- /dev/null
+++ b/examples/device/cdc_uac2/CMakeLists.txt
@@ -0,0 +1,38 @@
+cmake_minimum_required(VERSION 3.17)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
+
+# gets PROJECT name for the example (e.g. -)
+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/cdc_app.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/uac2_app.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... see the corresponding function
+# in hw/bsp/FAMILY/family.cmake for details.
+family_configure_device_example(${PROJECT} noos)
+
+# Uncomment me to enable UART based debugging
+# pico_enable_stdio_uart(${PROJECT} 1)
diff --git a/examples/device/cdc_uac2/Makefile b/examples/device/cdc_uac2/Makefile
new file mode 100644
index 000000000..21dcdb0b2
--- /dev/null
+++ b/examples/device/cdc_uac2/Makefile
@@ -0,0 +1,16 @@
+include ../../build_system/make/make.mk
+
+INC += \
+ src \
+ $(TOP)/hw \
+
+# Example source
+EXAMPLE_SOURCE += \
+ src/cdc_app.c \
+ src/main.c \
+ src/uac2_app.c \
+ src/usb_descriptors.c \
+
+SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
+
+include ../../build_system/make/rules.mk
diff --git a/examples/device/cdc_uac2/README.md b/examples/device/cdc_uac2/README.md
new file mode 100644
index 000000000..5d120be7d
--- /dev/null
+++ b/examples/device/cdc_uac2/README.md
@@ -0,0 +1,52 @@
+#### Composite CDC + UAC2 on Pico
+
+This example provides a composite CDC + UAC2 device on top of a Raspberry Pi
+Pico board.
+
+
+#### Use Cases
+
+- The CDC + UAC2 composite device happens to be important, especially in the
+ amateur radio community.
+
+ Modern radios (`rigs`) like Icom IC-7300 + IC-705 expose a sound card and a
+ serial device (`composite device`) to the computer over a single USB cable.
+ This allows for Audio I/O and CAT control over a single USB cable which is
+ very convenient.
+
+ By including and maintaining this example in TinyUSB repository, we enable
+ the amateur radio community to build (`homebrew`) radios with similar
+ functionality as the (expensive) commercial rigs.
+
+ This PR is important in bridging this specific gap between the commercial
+ rigs and homebrew equipment.
+
+- https://digirig.net/digirig-mobile-rev-1-9/ is a digital interface for
+ interfacing radios (that lack an inbuilt digital interface) with computers.
+ Digirig Mobile works brilliantly (is OSS!) and is a big improvement over
+ traditional digital interfaces (like the SignaLink USB Interface). By using a
+ Raspberry Pi Pico powered CDC + UAC2 composite device, we can simplify the
+ Digirig Mobile schematic, drastically reduce the manufacturing cost, and
+ (again) enable the homebrewers community to homebrew a modern digital interface
+ with ease themselves.
+
+
+#### Build Steps
+
+```
+cd examples/device/cdc_uac2
+
+export PICO_SDK_PATH=$HOME/pico-sdk
+
+cmake -DFAMILY=rp2040 pico .
+
+cmake -DFAMILY=rp2040 -DCMAKE_BUILD_TYPE=Debug # use this for debugging
+
+make BOARD=raspberry_pi_pico all
+```
+
+
+#### Development Notes
+
+Please try to keep this code synchronized with the `uac2_headset` example
+included in this repository.
diff --git a/examples/device/cdc_uac2/src/cdc_app.c b/examples/device/cdc_uac2/src/cdc_app.c
new file mode 100644
index 000000000..2166c1d6b
--- /dev/null
+++ b/examples/device/cdc_uac2/src/cdc_app.c
@@ -0,0 +1,72 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ * Copyright (c) 2022 Angel Molina (angelmolinu@gmail.com)
+ *
+ * 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 "common.h"
+
+// 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) itf;
+ (void) rts;
+
+ if (dtr)
+ {
+ // Terminal connected
+ }
+ else
+ {
+ // Terminal disconnected
+ }
+}
+
+// Invoked when CDC interface received data from host
+void tud_cdc_rx_cb(uint8_t itf)
+{
+ uint8_t buf[64];
+ uint32_t count;
+
+ // connected() check for DTR bit
+ // Most but not all terminal client set this when making connection
+ if (tud_cdc_connected())
+ {
+ if (tud_cdc_available()) // data is available
+ {
+ count = tud_cdc_n_read(itf, buf, sizeof(buf));
+ (void) count;
+
+ tud_cdc_n_write(itf, buf, count);
+ tud_cdc_n_write_flush(itf);
+ // dummy code to check that cdc serial is responding
+ board_led_write(0);
+ board_delay(50);
+ board_led_write(1);
+ board_delay(50);
+ board_led_write(0);
+ }
+ }
+}
diff --git a/examples/device/cdc_uac2/src/common.h b/examples/device/cdc_uac2/src/common.h
new file mode 100644
index 000000000..f281024c7
--- /dev/null
+++ b/examples/device/cdc_uac2/src/common.h
@@ -0,0 +1,34 @@
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
+/* Blink pattern
+ * - 25 ms : streaming data
+ * - 250 ms : device not mounted
+ * - 1000 ms : device mounted
+ * - 2500 ms : device is suspended
+ */
+enum
+{
+ BLINK_STREAMING = 25,
+ BLINK_NOT_MOUNTED = 250,
+ BLINK_MOUNTED = 1000,
+ BLINK_SUSPENDED = 2500,
+};
+
+enum
+{
+ VOLUME_CTRL_0_DB = 0,
+ VOLUME_CTRL_10_DB = 2560,
+ VOLUME_CTRL_20_DB = 5120,
+ VOLUME_CTRL_30_DB = 7680,
+ VOLUME_CTRL_40_DB = 10240,
+ VOLUME_CTRL_50_DB = 12800,
+ VOLUME_CTRL_60_DB = 15360,
+ VOLUME_CTRL_70_DB = 17920,
+ VOLUME_CTRL_80_DB = 20480,
+ VOLUME_CTRL_90_DB = 23040,
+ VOLUME_CTRL_100_DB = 25600,
+ VOLUME_CTRL_SILENCE = 0x8000,
+};
+
+#endif
diff --git a/examples/device/cdc_uac2/src/main.c b/examples/device/cdc_uac2/src/main.c
new file mode 100644
index 000000000..25b2cd9a5
--- /dev/null
+++ b/examples/device/cdc_uac2/src/main.c
@@ -0,0 +1,99 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Jerzy Kasenberg
+ * Copyright (c) 2022 Angel Molina
+ * Copyright (c) 2023 Dhiru Kholia
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include
+#include
+
+#include "bsp/board_api.h"
+#include "tusb.h"
+#include "common.h"
+
+extern uint32_t blink_interval_ms;
+
+#if (CFG_TUSB_MCU == OPT_MCU_RP2040)
+#include "pico/stdlib.h"
+#endif
+
+void led_blinking_task(void);
+
+/*------------- MAIN -------------*/
+int main(void)
+{
+ board_init();
+
+ // init device stack on configured roothub port
+ tud_init(BOARD_TUD_RHPORT);
+
+#if (CFG_TUSB_MCU == OPT_MCU_RP2040)
+ stdio_init_all();
+#endif
+
+ TU_LOG1("CDC UAC2 example running\r\n");
+
+ while (1)
+ {
+ tud_task(); // TinyUSB device task
+ led_blinking_task();
+
+#if (CFG_TUSB_MCU == OPT_MCU_RP2040)
+ // printf("Hello, world!\r\n");
+#endif
+ }
+
+ return 0;
+}
+
+//--------------------------------------------------------------------+
+// 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 = BLINK_MOUNTED;
+}
diff --git a/examples/device/cdc_uac2/src/tusb_config.h b/examples/device/cdc_uac2/src/tusb_config.h
new file mode 100644
index 000000000..93489cf62
--- /dev/null
+++ b/examples/device/cdc_uac2/src/tusb_config.h
@@ -0,0 +1,174 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Ha Thach (tinyusb.org)
+ * Copyright (c) 2020 Jerzy Kasenberg
+ *
+ * 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
+
+#include "usb_descriptors.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
+#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
+
+#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_CDC 1
+#define CFG_TUD_MSC 0
+#define CFG_TUD_HID 0
+#define CFG_TUD_MIDI 0
+#define CFG_TUD_AUDIO 1
+#define CFG_TUD_VENDOR 0
+
+//--------------------------------------------------------------------
+// AUDIO CLASS DRIVER CONFIGURATION
+//--------------------------------------------------------------------
+
+#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
+#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1
+#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX 1 // Changed
+
+// 16bit in 16bit slots
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX 2
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_TX 16
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX 2
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX 16
+
+#if defined(__RX__)
+// 8bit in 8bit slots
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX 1
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX 8
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX 1
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX 8
+#else
+// 24bit in 32bit slots
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX 4
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX 24
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX 4
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX 24
+#endif
+
+// 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_IN 1
+
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN 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)
+#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN 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)
+
+#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN)
+#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN) // Maximum EP IN size for all AS alternate settings used
+
+// 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_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_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
+
+// Size of control request buffer
+#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64
+
+// CDC FIFO size of TX and RX
+#define CFG_TUD_CDC_RX_BUFSIZE 64
+#define CFG_TUD_CDC_TX_BUFSIZE 64
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TUSB_CONFIG_H_ */
diff --git a/examples/device/cdc_uac2/src/uac2_app.c b/examples/device/cdc_uac2/src/uac2_app.c
new file mode 100644
index 000000000..c57d98a1a
--- /dev/null
+++ b/examples/device/cdc_uac2/src/uac2_app.c
@@ -0,0 +1,316 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Jerzy Kasenberg
+ * Copyright (c) 2022 Angel Molina (angelmolinu@gmail.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include
+#include
+
+#include "bsp/board_api.h"
+#include "tusb.h"
+#include "usb_descriptors.h"
+#include "common.h"
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF PROTOTYPES
+//--------------------------------------------------------------------+
+
+// List of supported sample rates
+const uint32_t sample_rates[] = {44100, 48000};
+uint32_t current_sample_rate = 44100;
+
+#define N_SAMPLE_RATES TU_ARRAY_SIZE(sample_rates)
+
+uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
+
+// Audio controls
+// Current states
+int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0
+int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0
+
+// Buffer for microphone data
+int32_t mic_buf[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ / 4];
+// Buffer for speaker data
+int32_t spk_buf[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ / 4];
+// Speaker data size received in the last frame
+int spk_data_size;
+// Resolution per format
+const uint8_t resolutions_per_format[CFG_TUD_AUDIO_FUNC_1_N_FORMATS] = {CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX};
+// Current resolution, update on format change
+uint8_t current_resolution;
+
+// Helper for clock get requests
+static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t const *request)
+{
+ TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK);
+
+ if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ)
+ {
+ if (request->bRequest == AUDIO_CS_REQ_CUR)
+ {
+ 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));
+ }
+ else if (request->bRequest == AUDIO_CS_REQ_RANGE)
+ {
+ audio_control_range_4_n_t(N_SAMPLE_RATES) rangef =
+ {
+ .wNumSubRanges = tu_htole16(N_SAMPLE_RATES)
+ };
+ TU_LOG1("Clock get %d freq ranges\r\n", N_SAMPLE_RATES);
+ for(uint8_t i = 0; i < N_SAMPLE_RATES; i++)
+ {
+ rangef.subrange[i].bMin = (int32_t) sample_rates[i];
+ rangef.subrange[i].bMax = (int32_t) sample_rates[i];
+ rangef.subrange[i].bRes = 0;
+ TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int)rangef.subrange[i].bMin, (int)rangef.subrange[i].bMax, (int)rangef.subrange[i].bRes);
+ }
+
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &rangef, sizeof(rangef));
+ }
+ }
+ else if (request->bControlSelector == AUDIO_CS_CTRL_CLK_VALID &&
+ request->bRequest == AUDIO_CS_REQ_CUR)
+ {
+ audio_control_cur_1_t cur_valid = { .bCur = 1 };
+ TU_LOG1("Clock get is valid %u\r\n", cur_valid.bCur);
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_valid, sizeof(cur_valid));
+ }
+ TU_LOG1("Clock get request not supported, entity = %u, selector = %u, request = %u\r\n",
+ request->bEntityID, request->bControlSelector, request->bRequest);
+ return false;
+}
+
+// Helper for clock set requests
+static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf)
+{
+ (void)rhport;
+
+ TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK);
+ TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR);
+
+ if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ)
+ {
+ TU_VERIFY(request->wLength == sizeof(audio_control_cur_4_t));
+
+ current_sample_rate = (uint32_t) ((audio_control_cur_4_t const *)buf)->bCur;
+
+ TU_LOG1("Clock set current freq: %" PRIu32 "\r\n", current_sample_rate);
+
+ return true;
+ }
+ else
+ {
+ TU_LOG1("Clock set request not supported, entity = %u, selector = %u, request = %u\r\n",
+ request->bEntityID, request->bControlSelector, request->bRequest);
+ return false;
+ }
+}
+
+// Helper for feature unit get requests
+static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_request_t const *request)
+{
+ TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT);
+
+ if (request->bControlSelector == AUDIO_FU_CTRL_MUTE && request->bRequest == AUDIO_CS_REQ_CUR)
+ {
+ audio_control_cur_1_t mute1 = { .bCur = mute[request->bChannelNumber] };
+ TU_LOG1("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur);
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &mute1, sizeof(mute1));
+ }
+ else if (UAC2_ENTITY_SPK_FEATURE_UNIT && request->bControlSelector == AUDIO_FU_CTRL_VOLUME)
+ {
+ if (request->bRequest == AUDIO_CS_REQ_RANGE)
+ {
+ audio_control_range_2_n_t(1) range_vol = {
+ .wNumSubRanges = tu_htole16(1),
+ .subrange[0] = { .bMin = tu_htole16(-VOLUME_CTRL_50_DB), tu_htole16(VOLUME_CTRL_0_DB), tu_htole16(256) }
+ };
+ TU_LOG1("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber,
+ range_vol.subrange[0].bMin / 256, range_vol.subrange[0].bMax / 256, range_vol.subrange[0].bRes / 256);
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &range_vol, sizeof(range_vol));
+ }
+ else if (request->bRequest == AUDIO_CS_REQ_CUR)
+ {
+ audio_control_cur_2_t cur_vol = { .bCur = tu_htole16(volume[request->bChannelNumber]) };
+ TU_LOG1("Get channel %u volume %d dB\r\n", request->bChannelNumber, cur_vol.bCur / 256);
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_vol, sizeof(cur_vol));
+ }
+ }
+ TU_LOG1("Feature unit get request not supported, entity = %u, selector = %u, request = %u\r\n",
+ request->bEntityID, request->bControlSelector, request->bRequest);
+
+ return false;
+}
+
+// Helper for feature unit set requests
+static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf)
+{
+ (void)rhport;
+
+ TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT);
+ TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR);
+
+ if (request->bControlSelector == AUDIO_FU_CTRL_MUTE)
+ {
+ TU_VERIFY(request->wLength == sizeof(audio_control_cur_1_t));
+
+ mute[request->bChannelNumber] = ((audio_control_cur_1_t const *)buf)->bCur;
+
+ TU_LOG1("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]);
+
+ return true;
+ }
+ else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME)
+ {
+ TU_VERIFY(request->wLength == sizeof(audio_control_cur_2_t));
+
+ volume[request->bChannelNumber] = ((audio_control_cur_2_t const *)buf)->bCur;
+
+ TU_LOG1("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256);
+
+ return true;
+ }
+ else
+ {
+ TU_LOG1("Feature unit set request not supported, entity = %u, selector = %u, request = %u\r\n",
+ request->bEntityID, request->bControlSelector, request->bRequest);
+ return false;
+ }
+}
+
+//--------------------------------------------------------------------+
+// Application Callback API Implementations
+//--------------------------------------------------------------------+
+
+// 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)
+{
+ audio_control_request_t const *request = (audio_control_request_t const *)p_request;
+
+ if (request->bEntityID == UAC2_ENTITY_CLOCK)
+ return tud_audio_clock_get_request(rhport, request);
+ if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT)
+ return tud_audio_feature_unit_get_request(rhport, request);
+ else
+ {
+ TU_LOG1("Get request not handled, entity = %d, selector = %d, request = %d\r\n",
+ request->bEntityID, request->bControlSelector, request->bRequest);
+ }
+ return false;
+}
+
+// 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 *buf)
+{
+ audio_control_request_t const *request = (audio_control_request_t const *)p_request;
+
+ if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT)
+ return tud_audio_feature_unit_set_request(rhport, request, buf);
+ if (request->bEntityID == UAC2_ENTITY_CLOCK)
+ return tud_audio_clock_set_request(rhport, request, buf);
+ TU_LOG1("Set request not handled, entity = %d, selector = %d, request = %d\r\n",
+ request->bEntityID, request->bControlSelector, request->bRequest);
+
+ return false;
+}
+
+bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request)
+{
+ (void)rhport;
+
+ uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex));
+ uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue));
+
+ if (ITF_NUM_AUDIO_STREAMING_SPK == itf && alt == 0) {
+ // Audio streaming stop
+ blink_interval_ms = BLINK_MOUNTED;
+ }
+
+ return true;
+}
+
+bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request)
+{
+ (void)rhport;
+ uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex));
+ uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue));
+
+ TU_LOG2("Set interface %d alt %d\r\n", itf, alt);
+ if (ITF_NUM_AUDIO_STREAMING_SPK == itf && alt != 0) {
+ // Audio streaming start
+ blink_interval_ms = BLINK_STREAMING;
+ }
+
+ // Clear buffer when streaming format is changed
+ spk_data_size = 0;
+ if(alt != 0)
+ {
+ current_resolution = resolutions_per_format[alt-1];
+ }
+
+ return true;
+}
+
+bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting)
+{
+ (void)rhport;
+ (void)func_id;
+ (void)ep_out;
+ (void)cur_alt_setting;
+
+ spk_data_size = tud_audio_read(spk_buf, n_bytes_received);
+ tud_audio_write(spk_buf, n_bytes_received);
+
+ return true;
+}
+
+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;
+
+ // This callback could be used to fill microphone data separately
+ return true;
+}
+
+//--------------------------------------------------------------------+
+// 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;
+ start_ms += blink_interval_ms;
+
+ board_led_write(led_state);
+ led_state = 1 - led_state;
+}
diff --git a/examples/device/cdc_uac2/src/usb_descriptors.c b/examples/device/cdc_uac2/src/usb_descriptors.c
new file mode 100644
index 000000000..72a695622
--- /dev/null
+++ b/examples/device/cdc_uac2/src/usb_descriptors.c
@@ -0,0 +1,216 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Ha Thach (tinyusb.org)
+ * Copyright (c) 2020 Jerzy Kasenberg
+ * Copyright (c) 2022 Angel Molina (angelmolinu@gmail.com)
+ *
+ * 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] 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)
+ // 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
+//--------------------------------------------------------------------+
+#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_HEADSET_STEREO_DESC_LEN + CFG_TUD_CDC * TUD_CDC_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_IN 0x03
+ #define EPNUM_AUDIO_OUT 0x03
+
+ #define EPNUM_CDC_NOTIF 0x84
+ #define EPNUM_CDC_OUT 0x05
+ #define EPNUM_CDC_IN 0x85
+
+#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_CDC_NOTIF 0x81
+ #define EPNUM_CDC_OUT 0x02
+ #define EPNUM_CDC_IN 0x82
+
+#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_CDC_NOTIF 0x83
+ #define EPNUM_CDC_OUT 0x04
+ #define EPNUM_CDC_IN 0x85
+
+#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_CDC_NOTIF 0x83
+ #define EPNUM_CDC_OUT 0x04
+ #define EPNUM_CDC_IN 0x85
+
+#else
+ #define EPNUM_AUDIO_IN 0x01
+ #define EPNUM_AUDIO_OUT 0x01
+
+ #define EPNUM_CDC_NOTIF 0x83
+ #define EPNUM_CDC_OUT 0x04
+ #define EPNUM_CDC_IN 0x84
+#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_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80),
+
+ // CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
+ TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 6, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64)
+};
+
+// 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)
+ "TinyUSB", // 1: Manufacturer
+ "TinyUSB headset", // 2: Product
+ NULL, // 3: Serials will use unique ID if possible
+ "TinyUSB Speakers", // 4: Audio Interface
+ "TinyUSB Microphone", // 5: Audio Interface
+ "TinyUSB CDC", // 6: 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/cdc_uac2/src/usb_descriptors.h b/examples/device/cdc_uac2/src/usb_descriptors.h
new file mode 100644
index 000000000..736feeefe
--- /dev/null
+++ b/examples/device/cdc_uac2/src/usb_descriptors.h
@@ -0,0 +1,158 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Jerzy Kasenbreg
+ * Copyright (c) 2022 Angel Molina (angelmolinu@gmail.com)
+ *
+ * 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_
+
+// #include "tusb.h"
+
+// Unit numbers are arbitrary selected
+#define UAC2_ENTITY_CLOCK 0x04
+// Speaker path
+#define UAC2_ENTITY_SPK_INPUT_TERMINAL 0x01
+#define UAC2_ENTITY_SPK_FEATURE_UNIT 0x02
+#define UAC2_ENTITY_SPK_OUTPUT_TERMINAL 0x03
+// Microphone path
+#define UAC2_ENTITY_MIC_INPUT_TERMINAL 0x11
+#define UAC2_ENTITY_MIC_OUTPUT_TERMINAL 0x13
+
+enum
+{
+ ITF_NUM_AUDIO_CONTROL = 0,
+ ITF_NUM_AUDIO_STREAMING_SPK,
+ ITF_NUM_AUDIO_STREAMING_MIC,
+ ITF_NUM_CDC,
+ ITF_NUM_CDC_DATA,
+ ITF_NUM_TOTAL
+};
+
+#define TUD_AUDIO_HEADSET_STEREO_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\
+ + TUD_AUDIO_DESC_STD_AC_LEN\
+ + TUD_AUDIO_DESC_CS_AC_LEN\
+ + TUD_AUDIO_DESC_CLK_SRC_LEN\
+ + TUD_AUDIO_DESC_INPUT_TERM_LEN\
+ + TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN\
+ + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\
+ + TUD_AUDIO_DESC_INPUT_TERM_LEN\
+ + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\
+ /* Interface 1, Alternate 0 */\
+ + TUD_AUDIO_DESC_STD_AS_INT_LEN\
+ /* Interface 1, Alternate 0 */\
+ + TUD_AUDIO_DESC_STD_AS_INT_LEN\
+ + TUD_AUDIO_DESC_CS_AS_INT_LEN\
+ + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\
+ + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\
+ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\
+ /* Interface 1, Alternate 2 */\
+ + TUD_AUDIO_DESC_STD_AS_INT_LEN\
+ + TUD_AUDIO_DESC_CS_AS_INT_LEN\
+ + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\
+ + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\
+ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\
+ /* Interface 2, Alternate 0 */\
+ + TUD_AUDIO_DESC_STD_AS_INT_LEN\
+ /* Interface 2, Alternate 1 */\
+ + TUD_AUDIO_DESC_STD_AS_INT_LEN\
+ + TUD_AUDIO_DESC_CS_AS_INT_LEN\
+ + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\
+ + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\
+ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\
+ /* Interface 2, Alternate 2 */\
+ + TUD_AUDIO_DESC_STD_AS_INT_LEN\
+ + TUD_AUDIO_DESC_CS_AS_INT_LEN\
+ + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\
+ + 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) \
+ /* Standard Interface Association Descriptor (IAD) */\
+ TUD_AUDIO_DESC_IAD(/*_firstitfs*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ 3, /*_stridx*/ 0x00),\
+ /* Standard AC Interface Descriptor(4.7.1) */\
+ TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_nEPs*/ 0x00, /*_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) */\
+ TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ 3, /*_ctrl*/ 7, /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \
+ /* Input Terminal Descriptor(4.7.2.4) */\
+ TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x02, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\
+ /* Feature Unit Descriptor(4.7.2.8) */\
+ TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(/*_unitid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_srcid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrlch0master*/ (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch2*/ (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\
+ /* Output Terminal Descriptor(4.7.2.5) */\
+ TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_OUT_HEADPHONES, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\
+ /* Input Terminal Descriptor(4.7.2.4) */\
+ 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 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),\
+ /* Standard AS Interface Descriptor(4.9.1) */\
+ /* Interface 1, Alternate 1 - alternate interface for data streaming */\
+ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x05),\
+ /* Class-Specific AS Interface Descriptor(4.9.2) */\
+ TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
+ /* 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),\
+ /* 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 */\
+ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x05),\
+ /* Class-Specific AS Interface Descriptor(4.9.2) */\
+ TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
+ /* 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),\
+ /* 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) */\
+ /* Interface 2, Alternate 0 - default alternate setting with 0 bandwidth */\
+ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x04),\
+ /* Standard AS Interface Descriptor(4.9.1) */\
+ /* Interface 2, Alternate 1 - alternate interface for data streaming */\
+ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x04),\
+ /* Class-Specific AS Interface Descriptor(4.9.2) */\
+ TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
+ /* 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),\
+ /* 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 */\
+ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x04),\
+ /* Class-Specific AS Interface Descriptor(4.9.2) */\
+ TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
+ /* 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),\
+ /* 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)
+
+#endif
diff --git a/examples/device/dfu/CMakeLists.txt b/examples/device/dfu/CMakeLists.txt
index acaa54198..a01eb3456 100644
--- a/examples/device/dfu/CMakeLists.txt
+++ b/examples/device/dfu/CMakeLists.txt
@@ -1,14 +1,18 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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})
@@ -23,6 +27,6 @@ target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
+# 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/dfu/Makefile b/examples/device/dfu/Makefile
index 5148ed55a..52a24cdb0 100644
--- a/examples/device/dfu/Makefile
+++ b/examples/device/dfu/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -12,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/src/main.c b/examples/device/dfu/src/main.c
index 6bb183819..81fc0a62c 100644
--- a/examples/device/dfu/src/main.c
+++ b/examples/device/dfu/src/main.c
@@ -42,7 +42,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
@@ -77,13 +77,15 @@ int main(void)
// 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();
}
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -114,7 +116,7 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c
index 51a0d09f5..fd469aaf2 100644
--- a/examples/device/dfu/src/usb_descriptors.c
+++ b/examples/device/dfu/src/usb_descriptors.c
@@ -23,6 +23,7 @@
*
*/
+#include "bsp/board_api.h"
#include "tusb.h"
#include "class/dfu/dfu_device.h"
@@ -116,56 +117,65 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
- "123456", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
"FLASH", // 4: DFU Partition 1
"EEPROM", // 5: DFU Partition 2
};
-static uint16_t _desc_str[32];
+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;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }
- else
- {
- // 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
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- const char* str = string_desc_arr[index];
+ 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
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) {
- chr_count = 31;
- }
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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)((((uint16_t)TUSB_DESC_STRING) << 8 ) | (2u*chr_count + 2u));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/dfu_runtime/CMakeLists.txt b/examples/device/dfu_runtime/CMakeLists.txt
index abc4d91da..a01eb3456 100644
--- a/examples/device/dfu_runtime/CMakeLists.txt
+++ b/examples/device/dfu_runtime/CMakeLists.txt
@@ -1,14 +1,18 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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})
@@ -23,6 +27,6 @@ target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+# 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/dfu_runtime/Makefile b/examples/device/dfu_runtime/Makefile
index 69b633fea..1b4d398cf 100644
--- a/examples/device/dfu_runtime/Makefile
+++ b/examples/device/dfu_runtime/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -9,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/dfu_runtime/src/main.c b/examples/device/dfu_runtime/src/main.c
index bd9a91c27..170dde932 100644
--- a/examples/device/dfu_runtime/src/main.c
+++ b/examples/device/dfu_runtime/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -40,7 +40,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
@@ -72,13 +72,15 @@ int main(void)
// 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();
}
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -109,7 +111,7 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
// Invoked on DFU_DETACH request to reboot to the bootloader
diff --git a/examples/device/dfu_runtime/src/usb_descriptors.c b/examples/device/dfu_runtime/src/usb_descriptors.c
index 1b0a60551..7ac53d255 100644
--- a/examples/device/dfu_runtime/src/usb_descriptors.c
+++ b/examples/device/dfu_runtime/src/usb_descriptors.c
@@ -23,6 +23,7 @@
*
*/
+#include "bsp/board_api.h"
#include "tusb.h"
#include "class/dfu/dfu_rt_device.h"
@@ -112,55 +113,64 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
- "123456", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
"TinyUSB DFU runtime", // 4: DFU runtime
};
-static uint16_t _desc_str[32];
+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;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }
- else
- {
- // 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
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- const char* str = string_desc_arr[index];
+ 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
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) {
- chr_count = 31;
- }
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/dynamic_configuration/CMakeLists.txt b/examples/device/dynamic_configuration/CMakeLists.txt
index fa6e83b7e..2b20d2234 100644
--- a/examples/device/dynamic_configuration/CMakeLists.txt
+++ b/examples/device/dynamic_configuration/CMakeLists.txt
@@ -1,14 +1,18 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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})
@@ -24,6 +28,6 @@ target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+# 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/dynamic_configuration/Makefile b/examples/device/dynamic_configuration/Makefile
index 69b633fea..1b4d398cf 100644
--- a/examples/device/dynamic_configuration/Makefile
+++ b/examples/device/dynamic_configuration/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -9,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 d844feae8..833fd072c 100644
--- a/examples/device/dynamic_configuration/skip.txt
+++ b/examples/device/dynamic_configuration/skip.txt
@@ -1 +1,2 @@
-mcu:SAMD11
\ No newline at end of file
+mcu:SAMD11
+family:espressif
diff --git a/examples/device/dynamic_configuration/src/main.c b/examples/device/dynamic_configuration/src/main.c
index 33a603343..b6409c8e1 100644
--- a/examples/device/dynamic_configuration/src/main.c
+++ b/examples/device/dynamic_configuration/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -27,7 +27,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
@@ -59,6 +59,10 @@ int main(void)
// 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
@@ -66,8 +70,6 @@ int main(void)
cdc_task();
midi_task();
}
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -98,7 +100,7 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
diff --git a/examples/device/dynamic_configuration/src/msc_disk.c b/examples/device/dynamic_configuration/src/msc_disk.c
index e8cb03fdd..10c3ac6fe 100644
--- a/examples/device/dynamic_configuration/src/msc_disk.c
+++ b/examples/device/dynamic_configuration/src/msc_disk.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,7 +23,7 @@
*
*/
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
#if CFG_TUD_MSC
diff --git a/examples/device/dynamic_configuration/src/usb_descriptors.c b/examples/device/dynamic_configuration/src/usb_descriptors.c
index 092229b99..7f35b4b22 100644
--- a/examples/device/dynamic_configuration/src/usb_descriptors.c
+++ b/examples/device/dynamic_configuration/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,8 +23,8 @@
*
*/
+#include "bsp/board_api.h"
#include "tusb.h"
-#include "bsp/board.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.
@@ -183,7 +183,7 @@ uint8_t const desc_configuration_0[] =
};
-uint8_t const desc_configuraiton_1[] =
+uint8_t const desc_configuration_1[] =
{
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_1_NUM_TOTAL, 0, CONFIG_1_TOTAL_LEN, 0x00, 100),
@@ -199,58 +199,70 @@ uint8_t const desc_configuraiton_1[] =
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
{
(void) index; // for multiple configurations
- return mode ? desc_configuraiton_1 : desc_configuration_0;
+ return mode ? desc_configuration_1 : desc_configuration_0;
}
//--------------------------------------------------------------------+
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
- "123456", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
};
-static uint16_t _desc_str[32];
+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;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // 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
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/hid_boot_interface/CMakeLists.txt b/examples/device/hid_boot_interface/CMakeLists.txt
index abc4d91da..a01eb3456 100644
--- a/examples/device/hid_boot_interface/CMakeLists.txt
+++ b/examples/device/hid_boot_interface/CMakeLists.txt
@@ -1,14 +1,18 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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})
@@ -23,6 +27,6 @@ target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+# 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/hid_boot_interface/Makefile b/examples/device/hid_boot_interface/Makefile
index c6a9c5b21..52a24cdb0 100644
--- a/examples/device/hid_boot_interface/Makefile
+++ b/examples/device/hid_boot_interface/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -9,7 +8,7 @@ INC += \
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/hid_boot_interface/src/main.c b/examples/device/hid_boot_interface/src/main.c
index b13428041..7ad5c53c2 100644
--- a/examples/device/hid_boot_interface/src/main.c
+++ b/examples/device/hid_boot_interface/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -27,7 +27,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
#include "usb_descriptors.h"
@@ -59,6 +59,10 @@ int main(void)
// 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
@@ -98,7 +102,7 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
diff --git a/examples/device/hid_boot_interface/src/usb_descriptors.c b/examples/device/hid_boot_interface/src/usb_descriptors.c
index a0d7e9f15..d68ef16d9 100644
--- a/examples/device/hid_boot_interface/src/usb_descriptors.c
+++ b/examples/device/hid_boot_interface/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,6 +23,7 @@
*
*/
+#include "bsp/board_api.h"
#include "tusb.h"
#include "usb_descriptors.h"
@@ -130,51 +131,63 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
- "123456", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
};
-static uint16_t _desc_str[32];
+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;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // 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
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/hid_boot_interface/src/usb_descriptors.h b/examples/device/hid_boot_interface/src/usb_descriptors.h
index 57cf0e2c0..6fee9e223 100644
--- a/examples/device/hid_boot_interface/src/usb_descriptors.h
+++ b/examples/device/hid_boot_interface/src/usb_descriptors.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
diff --git a/examples/device/hid_composite/CMakeLists.txt b/examples/device/hid_composite/CMakeLists.txt
index abc4d91da..a01eb3456 100644
--- a/examples/device/hid_composite/CMakeLists.txt
+++ b/examples/device/hid_composite/CMakeLists.txt
@@ -1,14 +1,18 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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})
@@ -23,6 +27,6 @@ target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+# 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/hid_composite/Makefile b/examples/device/hid_composite/Makefile
index 69b633fea..1b4d398cf 100644
--- a/examples/device/hid_composite/Makefile
+++ b/examples/device/hid_composite/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -9,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/src/main.c b/examples/device/hid_composite/src/main.c
index 05315f266..dcf13079f 100644
--- a/examples/device/hid_composite/src/main.c
+++ b/examples/device/hid_composite/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -27,7 +27,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
#include "usb_descriptors.h"
@@ -60,6 +60,10 @@ int main(void)
// 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
@@ -67,8 +71,6 @@ int main(void)
hid_task();
}
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -99,7 +101,7 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c
index 2988baee2..e174db46d 100644
--- a/examples/device/hid_composite/src/usb_descriptors.c
+++ b/examples/device/hid_composite/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,6 +23,7 @@
*
*/
+#include "bsp/board_api.h"
#include "tusb.h"
#include "usb_descriptors.h"
@@ -177,51 +178,63 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
- "123456", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
};
-static uint16_t _desc_str[32];
+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;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // 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
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/hid_composite/src/usb_descriptors.h b/examples/device/hid_composite/src/usb_descriptors.h
index ca8925ad9..e733d31dd 100644
--- a/examples/device/hid_composite/src/usb_descriptors.h
+++ b/examples/device/hid_composite/src/usb_descriptors.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
diff --git a/examples/device/hid_composite_freertos/CMakeLists.txt b/examples/device/hid_composite_freertos/CMakeLists.txt
index ed734b954..eb22014fb 100644
--- a/examples/device/hid_composite_freertos/CMakeLists.txt
+++ b/examples/device/hid_composite_freertos/CMakeLists.txt
@@ -1,17 +1,34 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
-# use BOARD-Directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
+# gets PROJECT name for the example (e.g. -)
+family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-# Check for -DFAMILY=
-if(FAMILY MATCHES "^esp32s[2-3]")
- include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
- project(${PROJECT})
-else()
- message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
+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/hid_composite_freertos/Makefile b/examples/device/hid_composite_freertos/Makefile
index a354a90b6..88d602393 100644
--- a/examples/device/hid_composite_freertos/Makefile
+++ b/examples/device/hid_composite_freertos/Makefile
@@ -1,10 +1,9 @@
DEPS_SUBMODULES += lib/FreeRTOS-Kernel
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
FREERTOS_SRC = lib/FreeRTOS-Kernel
-FREERTOS_PORTABLE_SRC= $(FREERTOS_SRC)/portable/$(if $(USE_IAR),IAR,GCC)/$(FREERTOS_PORT)
+FREERTOS_PORTABLE_PATH= $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC)
INC += \
src \
@@ -18,7 +17,7 @@ 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
@@ -27,22 +26,22 @@ SRC_C += \
$(FREERTOS_SRC)/queue.c \
$(FREERTOS_SRC)/tasks.c \
$(FREERTOS_SRC)/timers.c \
- $(subst ../../../,,$(wildcard ../../../$(FREERTOS_PORTABLE_SRC)/*.c))
+ $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.c))
SRC_S += \
- $(subst ../../../,,$(wildcard ../../../$(FREERTOS_PORTABLE_SRC)/*.s))
+ $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.s))
# include heap manage if configSUPPORT_DYNAMIC_ALLOCATION = 1
# SRC_C += $(FREERTOS_SRC)/portable/MemMang/heap_1.c
# CFLAGS += -Wno-error=sign-compare
# Suppress FreeRTOSConfig.h warnings
-GCC_CFLAGS += -Wno-error=redundant-decls
+CFLAGS_GCC += -Wno-error=redundant-decls
# Suppress FreeRTOS source warnings
-GCC_CFLAGS += -Wno-error=cast-qual
+CFLAGS_GCC += -Wno-error=cast-qual
# FreeRTOS (lto + Os) linker issue
-LDFLAGS += -Wl,--undefined=vTaskSwitchContext
+LDFLAGS_GCC += -Wl,--undefined=vTaskSwitchContext
-include ../../rules.mk
+include ../../build_system/make/rules.mk
diff --git a/examples/device/hid_composite_freertos/skip.txt b/examples/device/hid_composite_freertos/skip.txt
index 49b8ee57b..a6f96b288 100644
--- a/examples/device/hid_composite_freertos/skip.txt
+++ b/examples/device/hid_composite_freertos/skip.txt
@@ -8,5 +8,6 @@ mcu:RP2040
mcu:SAMD11
mcu:SAMX7X
mcu:VALENTYUSB_EPTRI
+mcu:RAXXX
family:broadcom_32bit
family:broadcom_64bit
diff --git a/examples/device/hid_composite_freertos/src/CMakeLists.txt b/examples/device/hid_composite_freertos/src/CMakeLists.txt
index 25da8fcd7..6d912854f 100644
--- a/examples/device/hid_composite_freertos/src/CMakeLists.txt
+++ b/examples/device/hid_composite_freertos/src/CMakeLists.txt
@@ -1,35 +1,3 @@
idf_component_register(SRCS "main.c" "usb_descriptors.c"
INCLUDE_DIRS "."
- REQUIRES freertos soc)
-
-file(TO_NATIVE_PATH "${TOP}/hw/bsp/${FAMILY}/boards/${BOARD}/board.cmake" board_cmake)
-
-if(EXISTS ${board_cmake})
- include(${board_cmake})
-endif()
-
-target_include_directories(${COMPONENT_TARGET} PUBLIC
- "${TOP}/hw"
- "${TOP}/src"
-)
-
-target_compile_definitions(${COMPONENT_TARGET} PUBLIC
- ESP_PLATFORM
-)
-
-target_sources(${COMPONENT_TARGET} PUBLIC
- "${TOP}/src/tusb.c"
- "${TOP}/src/common/tusb_fifo.c"
- "${TOP}/src/device/usbd.c"
- "${TOP}/src/device/usbd_control.c"
- "${TOP}/src/class/cdc/cdc_device.c"
- "${TOP}/src/class/dfu/dfu_rt_device.c"
- "${TOP}/src/class/hid/hid_device.c"
- "${TOP}/src/class/midi/midi_device.c"
- "${TOP}/src/class/msc/msc_device.c"
- "${TOP}/src/class/net/ecm_rndis_device.c"
- "${TOP}/src/class/net/ncm_device.c"
- "${TOP}/src/class/usbtmc/usbtmc_device.c"
- "${TOP}/src/class/vendor/vendor_device.c"
- "${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c"
-)
+ REQUIRES boards tinyusb_src)
diff --git a/examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
index 9bef9bbbf..6cc7a6577 100644
--- a/examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
+++ b/examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
@@ -81,7 +81,7 @@
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
-#define configQUEUE_REGISTRY_SIZE 2
+#define configQUEUE_REGISTRY_SIZE 4
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
@@ -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 7c9619c4b..2bd545bc2 100644
--- a/examples/device/hid_composite_freertos/src/main.c
+++ b/examples/device/hid_composite_freertos/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -27,11 +27,11 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#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();
@@ -138,6 +138,10 @@ void usb_device_task(void* param)
// 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)
{
@@ -176,7 +180,14 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0);
+ if (tud_mounted())
+ {
+ xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0);
+ }
+ else
+ {
+ xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0);
+ }
}
//--------------------------------------------------------------------+
diff --git a/examples/device/hid_composite_freertos/src/tusb_config.h b/examples/device/hid_composite_freertos/src/tusb_config.h
index 935ae9453..0689e0f23 100644
--- a/examples/device/hid_composite_freertos/src/tusb_config.h
+++ b/examples/device/hid_composite_freertos/src/tusb_config.h
@@ -54,10 +54,12 @@
#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 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_composite_freertos/src/usb_descriptors.c b/examples/device/hid_composite_freertos/src/usb_descriptors.c
index 4df12d3db..85820de55 100644
--- a/examples/device/hid_composite_freertos/src/usb_descriptors.c
+++ b/examples/device/hid_composite_freertos/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,6 +23,7 @@
*
*/
+#include "bsp/board_api.h"
#include "tusb.h"
#include "usb_descriptors.h"
@@ -175,51 +176,63 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
- "123456", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
};
-static uint16_t _desc_str[32];
+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;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // 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
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/hid_composite_freertos/src/usb_descriptors.h b/examples/device/hid_composite_freertos/src/usb_descriptors.h
index ca8925ad9..e733d31dd 100644
--- a/examples/device/hid_composite_freertos/src/usb_descriptors.h
+++ b/examples/device/hid_composite_freertos/src/usb_descriptors.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
diff --git a/examples/device/hid_generic_inout/CMakeLists.txt b/examples/device/hid_generic_inout/CMakeLists.txt
index abc4d91da..a01eb3456 100644
--- a/examples/device/hid_generic_inout/CMakeLists.txt
+++ b/examples/device/hid_generic_inout/CMakeLists.txt
@@ -1,14 +1,18 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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})
@@ -23,6 +27,6 @@ target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+# 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/hid_generic_inout/Makefile b/examples/device/hid_generic_inout/Makefile
index 69b633fea..1b4d398cf 100644
--- a/examples/device/hid_generic_inout/Makefile
+++ b/examples/device/hid_generic_inout/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -9,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_generic_inout/hid_test.js b/examples/device/hid_generic_inout/hid_test.js
index daa958fd5..16bc723e2 100644
--- a/examples/device/hid_generic_inout/hid_test.js
+++ b/examples/device/hid_generic_inout/hid_test.js
@@ -48,7 +48,7 @@ if( deviceInfo ) {
function anySupportedBoard(d) {
-
+
for (var key in boards) {
if (boards.hasOwnProperty(key)) {
if (isDevice(boards[key],d)) {
@@ -65,4 +65,3 @@ function isDevice(board,d){
// product id 0xff is matches all
return d.vendorId==board[0] && (d.productId==board[1] || board[1] == 0xFFFF);
}
-
diff --git a/examples/device/hid_generic_inout/src/main.c b/examples/device/hid_generic_inout/src/main.c
index 5b7daf118..cfa9f6283 100644
--- a/examples/device/hid_generic_inout/src/main.c
+++ b/examples/device/hid_generic_inout/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -27,7 +27,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
/* This example demonstrate HID Generic raw Input & Output.
@@ -83,13 +83,15 @@ int main(void)
// 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();
}
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -120,7 +122,7 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c
index cd4838407..64f6d17ae 100644
--- a/examples/device/hid_generic_inout/src/usb_descriptors.c
+++ b/examples/device/hid_generic_inout/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,6 +23,7 @@
*
*/
+#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.
@@ -120,51 +121,63 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
- "123456", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
};
-static uint16_t _desc_str[32];
+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;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // 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
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/hid_multiple_interface/CMakeLists.txt b/examples/device/hid_multiple_interface/CMakeLists.txt
index abc4d91da..a01eb3456 100644
--- a/examples/device/hid_multiple_interface/CMakeLists.txt
+++ b/examples/device/hid_multiple_interface/CMakeLists.txt
@@ -1,14 +1,18 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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})
@@ -23,6 +27,6 @@ target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+# 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/hid_multiple_interface/Makefile b/examples/device/hid_multiple_interface/Makefile
index 69b633fea..1b4d398cf 100644
--- a/examples/device/hid_multiple_interface/Makefile
+++ b/examples/device/hid_multiple_interface/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -9,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/src/main.c b/examples/device/hid_multiple_interface/src/main.c
index 29ba74398..30b4ae055 100644
--- a/examples/device/hid_multiple_interface/src/main.c
+++ b/examples/device/hid_multiple_interface/src/main.c
@@ -27,7 +27,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
@@ -64,6 +64,10 @@ int main(void)
// 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
@@ -71,8 +75,6 @@ int main(void)
hid_task();
}
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -103,7 +105,7 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
diff --git a/examples/device/hid_multiple_interface/src/usb_descriptors.c b/examples/device/hid_multiple_interface/src/usb_descriptors.c
index 42471a961..86f567e8e 100644
--- a/examples/device/hid_multiple_interface/src/usb_descriptors.c
+++ b/examples/device/hid_multiple_interface/src/usb_descriptors.c
@@ -23,6 +23,7 @@
*
*/
+#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.
@@ -136,53 +137,65 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
- "123456", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
"Keyboard Interface", // 4: Interface 1 String
"Mouse Interface", // 5: Interface 2 String
};
-static uint16_t _desc_str[32];
+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;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // 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
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/midi_test/CMakeLists.txt b/examples/device/midi_test/CMakeLists.txt
index abc4d91da..e51f14c02 100644
--- a/examples/device/midi_test/CMakeLists.txt
+++ b/examples/device/midi_test/CMakeLists.txt
@@ -1,17 +1,20 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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/main.c
@@ -23,6 +26,6 @@ target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+# 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/midi_test/Makefile b/examples/device/midi_test/Makefile
index 5a455078e..7fa475da5 100644
--- a/examples/device/midi_test/Makefile
+++ b/examples/device/midi_test/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -9,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/src/main.c b/examples/device/midi_test/src/main.c
index 3310348bd..b1d51598f 100644
--- a/examples/device/midi_test/src/main.c
+++ b/examples/device/midi_test/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -27,7 +27,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
/* This MIDI example send sequence of note (on/off) repeatedly. To test on PC, you need to install
@@ -65,15 +65,16 @@ int main(void)
// 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();
midi_task();
}
-
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -104,7 +105,7 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c
index c84a873b1..9781d3d6f 100644
--- a/examples/device/midi_test/src/usb_descriptors.c
+++ b/examples/device/midi_test/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,13 +23,14 @@
*
*/
+#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] MIDI | HID | MSC | CDC [LSB]
+ * [MSB] 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) | \
@@ -133,51 +134,63 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
- "123456", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
};
-static uint16_t _desc_str[32];
+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;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // 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
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/msc_dual_lun/CMakeLists.txt b/examples/device/msc_dual_lun/CMakeLists.txt
index 9e834ae21..e69fead35 100644
--- a/examples/device/msc_dual_lun/CMakeLists.txt
+++ b/examples/device/msc_dual_lun/CMakeLists.txt
@@ -1,29 +1,34 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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/main.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_disk_dual.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
- )
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_disk_dual.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
+ )
# Example include
target_include_directories(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src
- )
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ )
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+# 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/msc_dual_lun/Makefile b/examples/device/msc_dual_lun/Makefile
index 5a455078e..7fa475da5 100644
--- a/examples/device/msc_dual_lun/Makefile
+++ b/examples/device/msc_dual_lun/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -9,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 3549c702a..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
\ No newline at end of file
+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 96790d20c..aabd0bf8a 100644
--- a/examples/device/msc_dual_lun/src/main.c
+++ b/examples/device/msc_dual_lun/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -27,7 +27,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
@@ -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,20 +50,20 @@ 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
tud_init(BOARD_TUD_RHPORT);
- while (1)
- {
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
+ while (1) {
tud_task(); // tinyusb device task
led_blinking_task();
}
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -71,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)
-{
- blink_interval_ms = BLINK_MOUNTED;
+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/msc_dual_lun/src/msc_disk_dual.c b/examples/device/msc_dual_lun/src/msc_disk_dual.c
index 2b773b43b..4f0f6410f 100644
--- a/examples/device/msc_dual_lun/src/msc_disk_dual.c
+++ b/examples/device/msc_dual_lun/src/msc_disk_dual.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,7 +23,7 @@
*
*/
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
#if CFG_TUD_MSC
diff --git a/examples/device/msc_dual_lun/src/usb_descriptors.c b/examples/device/msc_dual_lun/src/usb_descriptors.c
index d8dbb5ce3..c0610945f 100644
--- a/examples/device/msc_dual_lun/src/usb_descriptors.c
+++ b/examples/device/msc_dual_lun/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,6 +23,7 @@
*
*/
+#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.
@@ -141,51 +142,63 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
- "123456789012", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
};
-static uint16_t _desc_str[32];
+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;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // 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
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/net_lwip_webserver/CMakeLists.txt b/examples/device/net_lwip_webserver/CMakeLists.txt
index 9fe1a325e..a16b8bd71 100644
--- a/examples/device/net_lwip_webserver/CMakeLists.txt
+++ b/examples/device/net_lwip_webserver/CMakeLists.txt
@@ -1,83 +1,93 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
+include(${CMAKE_CURRENT_LIST_DIR}/../../../hw/bsp/family_support.cmake)
-if (EXISTS ${TOP}/lib/lwip/src)
- include(${TOP}/hw/bsp/family_support.cmake)
+# gets PROJECT name for the example (e.g. -)
+family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
- # gets PROJECT name for the example (e.g. -)
- family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
+set(LWIP ${TOP}/lib/lwip)
+if (NOT EXISTS ${LWIP}/src)
+ family_example_missing_dependency(${PROJECT} "lib/lwip")
+ return()
+endif()
- project(${PROJECT})
+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})
+# Checks this example is valid for the family and initializes the project
+family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
- add_executable(${PROJECT})
+add_executable(${PROJECT})
- # Example source
- target_sources(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
- )
+# Example source
+target_sources(${PROJECT} PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/src/main.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/usb_descriptors.c
+ )
- # Example include
- target_include_directories(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src
- ${TOP}/lib/lwip/src/include
- ${TOP}/lib/lwip/src/include/ipv4
- ${TOP}/lib/lwip/src/include/lwip/apps
- ${TOP}/lib/networking
- )
+# Example include
+target_include_directories(${PROJECT} PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/src
+ ${LWIP}/src/include
+ ${LWIP}/src/include/ipv4
+ ${LWIP}/src/include/lwip/apps
+ ${TOP}/lib/networking
+ )
- target_sources(${PROJECT} PUBLIC
- ${TOP}/lib/lwip/src/core/altcp.c
- ${TOP}/lib/lwip/src/core/altcp_alloc.c
- ${TOP}/lib/lwip/src/core/altcp_tcp.c
- ${TOP}/lib/lwip/src/core/def.c
- ${TOP}/lib/lwip/src/core/dns.c
- ${TOP}/lib/lwip/src/core/inet_chksum.c
- ${TOP}/lib/lwip/src/core/init.c
- ${TOP}/lib/lwip/src/core/ip.c
- ${TOP}/lib/lwip/src/core/mem.c
- ${TOP}/lib/lwip/src/core/memp.c
- ${TOP}/lib/lwip/src/core/netif.c
- ${TOP}/lib/lwip/src/core/pbuf.c
- ${TOP}/lib/lwip/src/core/raw.c
- ${TOP}/lib/lwip/src/core/stats.c
- ${TOP}/lib/lwip/src/core/sys.c
- ${TOP}/lib/lwip/src/core/tcp.c
- ${TOP}/lib/lwip/src/core/tcp_in.c
- ${TOP}/lib/lwip/src/core/tcp_out.c
- ${TOP}/lib/lwip/src/core/timeouts.c
- ${TOP}/lib/lwip/src/core/udp.c
- ${TOP}/lib/lwip/src/core/ipv4/autoip.c
- ${TOP}/lib/lwip/src/core/ipv4/dhcp.c
- ${TOP}/lib/lwip/src/core/ipv4/etharp.c
- ${TOP}/lib/lwip/src/core/ipv4/icmp.c
- ${TOP}/lib/lwip/src/core/ipv4/igmp.c
- ${TOP}/lib/lwip/src/core/ipv4/ip4.c
- ${TOP}/lib/lwip/src/core/ipv4/ip4_addr.c
- ${TOP}/lib/lwip/src/core/ipv4/ip4_frag.c
- ${TOP}/lib/lwip/src/netif/ethernet.c
- ${TOP}/lib/lwip/src/netif/slipif.c
- ${TOP}/lib/lwip/src/apps/http/httpd.c
- ${TOP}/lib/lwip/src/apps/http/fs.c
- ${TOP}/lib/networking/dhserver.c
- ${TOP}/lib/networking/dnserver.c
- ${TOP}/lib/networking/rndis_reports.c
- )
+# lib/networking sources
+target_sources(${PROJECT} PUBLIC
+ ${TOP}/lib/networking/dhserver.c
+ ${TOP}/lib/networking/dnserver.c
+ ${TOP}/lib/networking/rndis_reports.c
+ )
- # due to warnings from other net source, we need to prevent error from some of the warnings options
- target_compile_options(${PROJECT} PUBLIC
- -Wno-error=null-dereference
- -Wno-error=conversion
- -Wno-error=sign-conversion
- -Wno-error=sign-compare
- )
+# lwip sources
+target_sources(${PROJECT} PUBLIC
+ ${LWIP}/src/core/altcp.c
+ ${LWIP}/src/core/altcp_alloc.c
+ ${LWIP}/src/core/altcp_tcp.c
+ ${LWIP}/src/core/def.c
+ ${LWIP}/src/core/dns.c
+ ${LWIP}/src/core/inet_chksum.c
+ ${LWIP}/src/core/init.c
+ ${LWIP}/src/core/ip.c
+ ${LWIP}/src/core/mem.c
+ ${LWIP}/src/core/memp.c
+ ${LWIP}/src/core/netif.c
+ ${LWIP}/src/core/pbuf.c
+ ${LWIP}/src/core/raw.c
+ ${LWIP}/src/core/stats.c
+ ${LWIP}/src/core/sys.c
+ ${LWIP}/src/core/tcp.c
+ ${LWIP}/src/core/tcp_in.c
+ ${LWIP}/src/core/tcp_out.c
+ ${LWIP}/src/core/timeouts.c
+ ${LWIP}/src/core/udp.c
+ ${LWIP}/src/core/ipv4/autoip.c
+ ${LWIP}/src/core/ipv4/dhcp.c
+ ${LWIP}/src/core/ipv4/etharp.c
+ ${LWIP}/src/core/ipv4/icmp.c
+ ${LWIP}/src/core/ipv4/igmp.c
+ ${LWIP}/src/core/ipv4/ip4.c
+ ${LWIP}/src/core/ipv4/ip4_addr.c
+ ${LWIP}/src/core/ipv4/ip4_frag.c
+ ${LWIP}/src/netif/ethernet.c
+ ${LWIP}/src/netif/slipif.c
+ ${LWIP}/src/apps/http/httpd.c
+ ${LWIP}/src/apps/http/fs.c
+ )
- # Configure compilation flags and libraries for the example... see the corresponding function
- # in hw/bsp/FAMILY/family.cmake for details.
- family_configure_device_example(${PROJECT})
-endif()
\ No newline at end of file
+# due to warnings from other net source, we need to prevent error from some of the warnings options
+if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
+ target_compile_options(${PROJECT} PUBLIC
+ -Wno-error=null-dereference
+ -Wno-error=conversion
+ -Wno-error=sign-conversion
+ -Wno-error=sign-compare
+ )
+elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
+
+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/net_lwip_webserver/Makefile b/examples/device/net_lwip_webserver/Makefile
index 55bd820bd..22426ba0d 100644
--- a/examples/device/net_lwip_webserver/Makefile
+++ b/examples/device/net_lwip_webserver/Makefile
@@ -1,10 +1,9 @@
DEPS_SUBMODULES += lib/lwip
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
# suppress warning caused by lwip
-GCC_CFLAGS += \
+CFLAGS_GCC += \
-Wno-error=null-dereference \
-Wno-error=unused-parameter \
-Wno-error=unused-variable
@@ -68,4 +67,4 @@ SRC_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 68761b058..75aa2ef14 100644
--- a/examples/device/net_lwip_webserver/skip.txt
+++ b/examples/device/net_lwip_webserver/skip.txt
@@ -4,7 +4,9 @@ mcu:MSP430x5xx
mcu:NUC121
mcu:SAMD11
mcu:STM32L0
-mcu:MKL25ZXX
+mcu:KINETIS_KL
family:broadcom_64bit
family:broadcom_32bit
-board:curiosity_nano
\ No newline at end of file
+board:curiosity_nano
+board:frdm_kl25z
+family:espressif
diff --git a/examples/device/net_lwip_webserver/src/arch/cc.h b/examples/device/net_lwip_webserver/src/arch/cc.h
index 56a0cacf7..9f30b91cb 100644
--- a/examples/device/net_lwip_webserver/src/arch/cc.h
+++ b/examples/device/net_lwip_webserver/src/arch/cc.h
@@ -1,8 +1,8 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * derived from this software without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
- *
+ *
* Author: Adam Dunkels
*
*/
@@ -42,7 +42,7 @@ typedef int sys_prot_t;
#if defined (__ICCARM__)
#define PACK_STRUCT_BEGIN
-#define PACK_STRUCT_STRUCT
+#define PACK_STRUCT_STRUCT
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(x) x
#define PACK_STRUCT_USE_INCLUDES
@@ -50,7 +50,7 @@ typedef int sys_prot_t;
#elif defined (__CC_ARM)
#define PACK_STRUCT_BEGIN __packed
-#define PACK_STRUCT_STRUCT
+#define PACK_STRUCT_STRUCT
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(x) x
diff --git a/examples/device/net_lwip_webserver/src/lwipopts.h b/examples/device/net_lwip_webserver/src/lwipopts.h
index a215017c7..336c9243d 100644
--- a/examples/device/net_lwip_webserver/src/lwipopts.h
+++ b/examples/device/net_lwip_webserver/src/lwipopts.h
@@ -1,8 +1,8 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * derived from this software without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
- *
+ *
* Author: Simon Goldschmidt
*
*/
diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c
index 33b4d38b6..7d98aacbc 100644
--- a/examples/device/net_lwip_webserver/src/main.c
+++ b/examples/device/net_lwip_webserver/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020 Peter Lawrence
@@ -39,11 +39,11 @@ and likely their manufacturer has not tested such functionality. Some code work
The smartphone may only have an ECM driver, but refuse to automatically pick ECM (unlike the OSes above);
try modifying ./examples/devices/net_lwip_webserver/usb_descriptors.c so that CONFIG_ID_ECM is default.
-The smartphone may be artificially picky about which Ethernet MAC address to recognize; if this happens,
+The smartphone may be artificially picky about which Ethernet MAC address to recognize; if this happens,
try changing the first byte of tud_network_mac_address[] below from 0x02 to 0x00 (clearing bit 1).
*/
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
#include "dhserver.h"
@@ -64,7 +64,7 @@ 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 */
-const 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);
@@ -170,7 +170,7 @@ bool dns_query_proc(const char *name, ip4_addr_t *addr)
bool tud_network_recv_cb(const uint8_t *src, uint16_t size)
{
- /* this shouldn't happen, but if we get another packet before
+ /* 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;
@@ -232,6 +232,10 @@ int main(void)
// init device stack on configured roothub port
tud_init(BOARD_TUD_RHPORT);
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
/* initialize lwip, dhcp-server, dns-server, and http */
init_lwip();
while (!netif_is_up(&netif_data));
diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c
index bee51790a..da628c8be 100644
--- a/examples/device/net_lwip_webserver/src/usb_descriptors.c
+++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,6 +23,7 @@
*
*/
+#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.
@@ -77,7 +78,7 @@ tusb_desc_device_t const desc_device =
.bDeviceClass = TUSB_CLASS_MISC,
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
.bDeviceProtocol = MISC_PROTOCOL_IAD,
-
+
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.idVendor = 0xCafe,
@@ -190,55 +191,56 @@ static char const* string_desc_arr [] =
[STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409)
[STRID_MANUFACTURER] = "TinyUSB", // Manufacturer
[STRID_PRODUCT] = "TinyUSB Device", // Product
- [STRID_SERIAL] = "123456", // Serial
+ [STRID_SERIAL] = NULL, // Serials will use unique ID if possible
[STRID_INTERFACE] = "TinyUSB Network Interface" // Interface Description
// STRID_MAC index is handled separately
};
-static uint16_t _desc_str[32];
+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;
-
unsigned int chr_count = 0;
- if (STRID_LANGID == index)
- {
- memcpy(&_desc_str[1], string_desc_arr[STRID_LANGID], 2);
- chr_count = 1;
- }
- else if (STRID_MAC == index)
- {
- // Convert MAC address into UTF-16
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- for (unsigned i=0; i> 4) & 0xf];
- _desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 0) & 0xf];
- }
- }
- else
- {
- // 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
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ case STRID_MAC:
+ // Convert MAC address into UTF-16
+ for (unsigned i=0; i> 4) & 0xf];
+ _desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 0) & 0xf];
+ }
+ break;
- const char* str = string_desc_arr[index];
+ 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
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > (TU_ARRAY_SIZE(_desc_str) - 1)) chr_count = TU_ARRAY_SIZE(_desc_str) - 1;
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Convert ASCII string into UTF-16
- for (unsigned int i=0; i 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
diff --git a/examples/device/uac2_headset/CMakeLists.txt b/examples/device/uac2_headset/CMakeLists.txt
index abc4d91da..e92a57148 100644
--- a/examples/device/uac2_headset/CMakeLists.txt
+++ b/examples/device/uac2_headset/CMakeLists.txt
@@ -1,15 +1,20 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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
@@ -23,6 +28,6 @@ target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+# 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/uac2_headset/Makefile b/examples/device/uac2_headset/Makefile
index 5a455078e..7fa475da5 100644
--- a/examples/device/uac2_headset/Makefile
+++ b/examples/device/uac2_headset/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -9,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 003dc2a74..0ea6e7025 100644
--- a/examples/device/uac2_headset/src/main.c
+++ b/examples/device/uac2_headset/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jerzy Kasenberg
@@ -26,7 +26,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
#include "usb_descriptors.h"
@@ -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;
@@ -79,8 +75,8 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
// Audio controls
// Current states
-int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0
-int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0
+int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0
+int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0
// Buffer for microphone data
int32_t mic_buf[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ / 4];
@@ -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)
@@ -105,16 +102,19 @@ int main(void)
// init device stack on configured roothub port
tud_init(BOARD_TUD_RHPORT);
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
TU_LOG1("Headset running\r\n");
while (1)
{
tud_task(); // TinyUSB device task
audio_task();
+ audio_control_task();
led_blinking_task();
}
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -145,7 +145,7 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
// Helper for clock get requests
@@ -157,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));
@@ -176,7 +176,7 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t
rangef.subrange[i].bRes = 0;
TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int)rangef.subrange[i].bMin, (int)rangef.subrange[i].bMax, (int)rangef.subrange[i].bRes);
}
-
+
return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &rangef, sizeof(rangef));
}
}
@@ -206,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;
}
@@ -426,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 07c86b903..ff4dc2acc 100644
--- a/examples/device/uac2_headset/src/usb_descriptors.c
+++ b/examples/device/uac2_headset/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020 Ha Thach (tinyusb.org)
@@ -24,6 +24,7 @@
*
*/
+#include "bsp/board_api.h"
#include "tusb.h"
#include "usb_descriptors.h"
@@ -46,7 +47,7 @@ tusb_desc_device_t const desc_device =
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0200,
- // Use Interface Association Descriptor (IAD) for CDC
+ // 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,
@@ -81,36 +82,41 @@ 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[] =
{
- // Interface count, string index, total length, attribute, power in mA
+ // 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_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
@@ -126,52 +132,65 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB headset", // 2: Product
- "000001", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
"TinyUSB Speakers", // 4: Audio Interface
"TinyUSB Microphone", // 5: Audio Interface
};
-static uint16_t _desc_str[32];
+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;
+uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
+ (void) langid;
+ size_t chr_count;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if (index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }
- else
- {
- // Convert ASCII string into UTF-16
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if (!(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0]))) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if (chr_count > 31) chr_count = 31;
+ const char *str = string_desc_arr[index];
- for (uint8_t i = 0; i < chr_count; i++)
- {
- _desc_str[1 + i] = str[i];
- }
+ // 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/uac2_headset/src/usb_descriptors.h b/examples/device/uac2_headset/src/usb_descriptors.h
index 342b4fac1..da0da83e8 100644
--- a/examples/device/uac2_headset/src/usb_descriptors.h
+++ b/examples/device/uac2_headset/src/usb_descriptors.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jerzy Kasenbreg
@@ -55,9 +55,10 @@ 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 0 */\
+ /* Interface 1, Alternate 1 */\
+ TUD_AUDIO_DESC_STD_AS_INT_LEN\
+ TUD_AUDIO_DESC_CS_AS_INT_LEN\
+ TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\
@@ -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(/*_firstitfs*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ 3, /*_stridx*/ 0x00),\
+ 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*/ (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*/ (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*/ (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*/ (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/CMakeLists.txt b/examples/device/usbtmc/CMakeLists.txt
index c49603c26..a63ca2d81 100644
--- a/examples/device/usbtmc/CMakeLists.txt
+++ b/examples/device/usbtmc/CMakeLists.txt
@@ -1,15 +1,20 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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
@@ -24,6 +29,6 @@ target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+# 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/usbtmc/Makefile b/examples/device/usbtmc/Makefile
index 69b633fea..1b4d398cf 100644
--- a/examples/device/usbtmc/Makefile
+++ b/examples/device/usbtmc/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -9,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/usbtmc/src/main.c b/examples/device/usbtmc/src/main.c
index 6945d8743..9d8f0783d 100644
--- a/examples/device/usbtmc/src/main.c
+++ b/examples/device/usbtmc/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -27,7 +27,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
#include "usbtmc_app.h"
//--------------------------------------------------------------------+
@@ -57,14 +57,16 @@ int main(void)
// 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();
usbtmc_app_task_iter();
}
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -95,7 +97,7 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c
index ff682ff97..54948291e 100644
--- a/examples/device/usbtmc/src/usb_descriptors.c
+++ b/examples/device/usbtmc/src/usb_descriptors.c
@@ -23,6 +23,7 @@
*
*/
+#include "bsp/board_api.h"
#include "tusb.h"
#include "class/usbtmc/usbtmc.h"
#include "class/usbtmc/usbtmc_device.h"
@@ -188,55 +189,64 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
- "123456", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
"TinyUSB USBTMC", // 4: USBTMC
};
-static uint16_t _desc_str[32];
+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;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }
- else
- {
- // 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
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- const char* str = string_desc_arr[index];
+ 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
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) {
- chr_count = 31;
- }
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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)((((uint16_t)TUSB_DESC_STRING) << 8 ) | (2u*chr_count + 2u));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c
index 503ee3071..fb25982c7 100644
--- a/examples/device/usbtmc/src/usbtmc_app.c
+++ b/examples/device/usbtmc/src/usbtmc_app.c
@@ -26,7 +26,7 @@
#include
#include /* atoi */
#include "tusb.h"
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "main.h"
#if (CFG_TUD_USBTMC_ENABLE_488)
@@ -88,14 +88,6 @@ static size_t buffer_tx_ix; // for transmitting using multiple transfers
static uint8_t buffer[225]; // A few packets long should be enough.
-static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = {
- .bmTransferAttributes =
- {
- .EOM = 1,
- .UsingTermChar = 0
- }
-};
-
void tud_usbtmc_open_cb(uint8_t interface_id)
{
(void)interface_id;
@@ -148,12 +140,14 @@ bool tud_usbtmc_msg_data_cb(void *data, size_t len, bool transfer_complete)
queryState = transfer_complete;
idnQuery = 0;
- if ( transfer_complete && (len >= 4) && (!strncmp("*idn?", data, 4) || !strncmp("*IDN?", data, 4)) )
+ if ( transfer_complete && (len >= 4) &&
+ (!strncmp("*idn?", data, 4) || !strncmp("*IDN?", data, 4)) )
{
idnQuery = 1;
}
- if ( transfer_complete && (!strncmp("delay ", data, 5) || !strncmp("DELAY ", data, 5)) )
+ if ( transfer_complete &&
+ (!strncmp("delay ", data, 5) || !strncmp("DELAY ", data, 5)) )
{
queryState = 0;
int d = atoi((char*)data + 5);
@@ -185,9 +179,6 @@ static unsigned int msgReqLen;
bool tud_usbtmc_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request)
{
- rspMsg.header.MsgID = request->header.MsgID,
- rspMsg.header.bTag = request->header.bTag,
- rspMsg.header.bTagInverse = request->header.bTagInverse;
msgReqLen = request->TransferSize;
#ifdef xDEBUG
@@ -251,7 +242,6 @@ void usbtmc_app_task_iter(void) {
break;
default:
TU_ASSERT(false,);
- return;
}
}
diff --git a/examples/device/usbtmc/visaQuery.py b/examples/device/usbtmc/visaQuery.py
index c4e5ad2b9..ca65daf97 100644
--- a/examples/device/usbtmc/visaQuery.py
+++ b/examples/device/usbtmc/visaQuery.py
@@ -36,8 +36,8 @@ def test_trig():
time.sleep(0.3) # SRQ may have some delay
assert (inst.read_stb() & 0x40), "SRQ not set after 0.3 seconds"
assert (inst.read_stb() == 0)
-
-
+
+
def test_mav():
inst.write("delay 50")
inst.read_stb() # clear STB
@@ -45,15 +45,15 @@ def test_mav():
inst.write("123")
time.sleep(0.3)
assert (inst.read_stb() & 0x10), "MAV not set after 0.5 seconds"
-
+
rsp = inst.read()
assert(rsp == "123\r\n")
-
-
+
+
def test_srq():
assert (inst.read_stb() == 0)
inst.write("123")
-
+
#inst.enable_event(pyvisa.constants.VI_EVENT_SERVICE_REQ, pyvisa.constants.VI_QUEUE)
#waitrsp = inst.wait_on_event(pyvisa.constants.VI_EVENT_SERVICE_REQ, 5000)
#inst.discard_events(pyvisa.constants.VI_EVENT_SERVICE_REQ, pyvisa.constants.VI_QUEUE)
@@ -64,7 +64,7 @@ def test_srq():
assert (stb == 0x50),msg
assert (inst.read_stb() == 0x10), "SRQ set at second read!"
-
+
rsp = inst.read()
assert(rsp == "123\r\n")
@@ -110,7 +110,7 @@ def test_abort_in():
inst.timeout = 800
y = inst.read()
assert(y == "xxx\r\n")
-
+
def test_indicate():
# perform indicator pulse
usb_iface = inst.get_visa_attribute(pyvisa.constants.VI_ATTR_USB_INTFC_NUM)
@@ -120,8 +120,8 @@ def test_indicate():
assert(retv == b'\x01')
else:
assert((retv[1] == pyvisa.constants.StatusCode(0)) and (retv[0] == b'\x01')), f"indicator pulse failed: retv={retv}"
-
-
+
+
def test_multi_read():
old_chunk_size = inst.chunk_size
longstr = "0123456789abcdefghijklmnopqrstuvwxyz" * 10
@@ -133,7 +133,7 @@ def test_multi_read():
y = inst.read()
assert (x + "\r\n" == y)
#inst.chunk_size = old_chunk_size
-
+
def test_stall_ep0():
usb_iface = inst.get_visa_attribute(pyvisa.constants.VI_ATTR_USB_INTFC_NUM)
inst.read_stb()
@@ -143,7 +143,7 @@ def test_stall_ep0():
assert(False)
except pyvisa.VisaIOError:
pass
-
+
assert (inst.read_stb() == 0)
@@ -153,7 +153,7 @@ print(reslist)
if (len(reslist) == 0):
sys.exit()
-
+
inst = rm.open_resource(reslist[0]);
inst.timeout = 3000
diff --git a/examples/device/video_capture/CMakeLists.txt b/examples/device/video_capture/CMakeLists.txt
index b92a2b804..80dc39ca5 100644
--- a/examples/device/video_capture/CMakeLists.txt
+++ b/examples/device/video_capture/CMakeLists.txt
@@ -1,15 +1,20 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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)
@@ -29,6 +34,6 @@ target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+# 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/Makefile b/examples/device/video_capture/Makefile
index fda66bcc1..d698a848d 100644
--- a/examples/device/video_capture/Makefile
+++ b/examples/device/video_capture/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
ifeq ($(DISABLE_MJPEG),1)
CFLAGS += -DCFG_EXAMPLE_VIDEO_DISABLE_MJPEG
@@ -16,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 3ceebe821..ddb51e03a 100644
--- a/examples/device/video_capture/src/main.c
+++ b/examples/device/video_capture/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -27,7 +27,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
#include "usb_descriptors.h"
@@ -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,26 +48,38 @@ 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);
- while (1)
- {
- tud_task(); // tinyusb device task
- led_blinking_task();
-
- video_task();
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
}
- return 0;
+ while (1) {
+ tud_task(); // tinyusb device task
+ led_blinking_task(NULL);
+ video_task(NULL);
+ }
+#endif
}
//--------------------------------------------------------------------+
@@ -75,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)
-{
- blink_interval_ms = BLINK_MOUNTED;
+void tud_resume_cb(void) {
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
-
//--------------------------------------------------------------------+
// USB Video
//--------------------------------------------------------------------+
@@ -109,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;
@@ -127,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) {
@@ -161,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) {
@@ -168,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
}
@@ -201,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 e567ba669..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,9 +102,15 @@
// 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 1
+
+//#define CFG_EXAMPLE_VIDEO_READONLY
+//#define CFG_EXAMPLE_VIDEO_DISABLE_MJPEG
+
#ifdef __cplusplus
}
#endif
diff --git a/examples/device/video_capture/src/usb_descriptors.c b/examples/device/video_capture/src/usb_descriptors.c
index 0cf772010..5011bee18 100644
--- a/examples/device/video_capture/src/usb_descriptors.c
+++ b/examples/device/video_capture/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,6 +23,7 @@
*
*/
+#include "bsp/board_api.h"
#include "tusb.h"
#include "usb_descriptors.h"
@@ -36,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)
@@ -53,125 +76,409 @@ 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)
-#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_DESC_MJPEG_LEN)
-#else
-#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN)
-#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 ...
- #define EPNUM_VIDEO_IN 0x83
-
+ #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 0x88
-
+ #define EPNUM_VIDEO_IN (CFG_TUD_VIDEO_STREAMING_BULK ? 0x81 : 0x88)
#else
#define EPNUM_VIDEO_IN 0x81
-
#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),
-
- // IAD for Video Control
#if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG)
- TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(4, EPNUM_VIDEO_IN,
- FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE,
- CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE)
+ #define USE_MJPEG 1
#else
- TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(4, EPNUM_VIDEO_IN,
- FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE,
- CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE)
+ #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
+ 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
+
+ tusb_desc_endpoint_t ep;
+} uvc_streaming_desc_t;
+
+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
+ .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
//--------------------------------------------------------------------+
-// 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
- "123456", // 3: Serials, should use chip ID
- "TinyUSB UVC", // 4: UVC Interface
-};
-
-static uint16_t _desc_str[32];
+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;
- uint8_t chr_count;
+ switch (index) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // 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
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if (index >= sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char* str = string_desc_arr[index];
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/video_capture/src/usb_descriptors.h b/examples/device/video_capture/src/usb_descriptors.h
index f1ed3c8e9..12d41b2f3 100644
--- a/examples/device/video_capture/src/usb_descriptors.h
+++ b/examples/device/video_capture/src/usb_descriptors.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jerzy Kasenbreg
@@ -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\
@@ -79,6 +69,38 @@ enum {
+ 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 */
@@ -94,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), \
@@ -120,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 */\
@@ -131,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), \
@@ -165,4 +175,64 @@ enum {
/* 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/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. -)
+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..b36abf721
--- /dev/null
+++ b/examples/device/video_capture_2ch/skip.txt
@@ -0,0 +1,13 @@
+mcu:MSP430x5xx
+mcu:NUC121
+mcu:SAMD11
+mcu:GD32VF103
+mcu:CH32V307
+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
+#include
+#include
+
+#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/CMakeLists.txt b/examples/device/webusb_serial/CMakeLists.txt
index abc4d91da..e92a57148 100644
--- a/examples/device/webusb_serial/CMakeLists.txt
+++ b/examples/device/webusb_serial/CMakeLists.txt
@@ -1,15 +1,20 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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
@@ -23,6 +28,6 @@ target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_device_example(${PROJECT})
\ No newline at end of file
+# 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/webusb_serial/Makefile b/examples/device/webusb_serial/Makefile
index 5a455078e..7fa475da5 100644
--- a/examples/device/webusb_serial/Makefile
+++ b/examples/device/webusb_serial/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -9,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/webusb_serial/src/main.c b/examples/device/webusb_serial/src/main.c
index 604d30a83..800d435b8 100644
--- a/examples/device/webusb_serial/src/main.c
+++ b/examples/device/webusb_serial/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -47,7 +47,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
#include "usb_descriptors.h"
@@ -96,6 +96,10 @@ int main(void)
// 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
@@ -103,8 +107,6 @@ int main(void)
webserial_task();
led_blinking_task();
}
-
- return 0;
}
// send characters to both CDC and WebUSB
@@ -114,7 +116,7 @@ void echo_all(uint8_t buf[], uint32_t count)
if ( web_serial_connected )
{
tud_vendor_write(buf, count);
- tud_vendor_flush();
+ tud_vendor_write_flush();
}
// echo to cdc
@@ -158,7 +160,7 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
@@ -213,7 +215,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ
blink_interval_ms = BLINK_ALWAYS_ON;
tud_vendor_write_str("\r\nWebUSB interface connected\r\n");
- tud_vendor_flush();
+ tud_vendor_write_flush();
}else
{
blink_interval_ms = BLINK_MOUNTED;
diff --git a/examples/device/webusb_serial/src/usb_descriptors.c b/examples/device/webusb_serial/src/usb_descriptors.c
index 99f5caaf9..b01fae8e3 100644
--- a/examples/device/webusb_serial/src/usb_descriptors.c
+++ b/examples/device/webusb_serial/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,6 +23,7 @@
*
*/
+#include "bsp/board_api.h"
#include "tusb.h"
#include "usb_descriptors.h"
@@ -207,53 +208,65 @@ TU_VERIFY_STATIC(sizeof(desc_ms_os_20) == MS_OS_20_DESC_LEN, "Incorrect size");
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
- "123456", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
"TinyUSB CDC", // 4: CDC Interface
"TinyUSB WebUSB" // 5: Vendor Interface
};
-static uint16_t _desc_str[32];
+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;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // 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
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/device/webusb_serial/src/usb_descriptors.h b/examples/device/webusb_serial/src/usb_descriptors.h
index 19f1ff3f3..a1c4a2cf1 100644
--- a/examples/device/webusb_serial/src/usb_descriptors.h
+++ b/examples/device/webusb_serial/src/usb_descriptors.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
diff --git a/examples/dual/CMakeLists.txt b/examples/dual/CMakeLists.txt
index d2f9a42f0..15081cf26 100644
--- a/examples/dual/CMakeLists.txt
+++ b/examples/dual/CMakeLists.txt
@@ -1,12 +1,13 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake)
-project(tinyusb_dual_examples)
+project(tinyusb_dual_examples C CXX ASM)
family_initialize_project(tinyusb_dual_examples ${CMAKE_CURRENT_LIST_DIR})
+
if (FAMILY STREQUAL "rp2040" AND NOT TARGET tinyusb_pico_pio_usb)
- message("Skipping dual host/device mode examples as Pico-PIO-USB is not available")
-else()
- # family_add_subdirectory will filter what to actually add based on selected FAMILY
- family_add_subdirectory(host_hid_to_device_cdc)
-endif()
+ message("Skipping dual host/device mode examples as Pico-PIO-USB is not available")
+else ()
+ # family_add_subdirectory will filter what to actually add based on selected FAMILY
+ family_add_subdirectory(host_hid_to_device_cdc)
+endif ()
diff --git a/examples/dual/host_hid_to_device_cdc/CMakeLists.txt b/examples/dual/host_hid_to_device_cdc/CMakeLists.txt
index 724d1e119..a6557c2d0 100644
--- a/examples/dual/host_hid_to_device_cdc/CMakeLists.txt
+++ b/examples/dual/host_hid_to_device_cdc/CMakeLists.txt
@@ -1,11 +1,11 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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})
@@ -14,27 +14,27 @@ add_executable(${PROJECT})
# Example source
target_sources(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.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
- )
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ )
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_dual_usb_example(${PROJECT})
+# Configure compilation flags and libraries for the example without RTOS.
+# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
+family_configure_dual_usb_example(${PROJECT} noos)
# due to warnings from Pico-PIO-USB
target_compile_options(${PROJECT} PUBLIC
- -Wno-error=shadow
- -Wno-error=cast-align
- -Wno-error=cast-qual
- -Wno-error=redundant-decls
- -Wno-error=sign-conversion
- -Wno-error=conversion
- -Wno-error=sign-compare
- -Wno-error=unused-function
- )
+ -Wno-error=shadow
+ -Wno-error=cast-align
+ -Wno-error=cast-qual
+ -Wno-error=redundant-decls
+ -Wno-error=sign-conversion
+ -Wno-error=conversion
+ -Wno-error=sign-compare
+ -Wno-error=unused-function
+ )
diff --git a/examples/dual/host_hid_to_device_cdc/Makefile b/examples/dual/host_hid_to_device_cdc/Makefile
index 3fe9b0888..2c2168f5d 100644
--- a/examples/dual/host_hid_to_device_cdc/Makefile
+++ b/examples/dual/host_hid_to_device_cdc/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -16,4 +15,4 @@ SRC_C += \
src/host/hub.c \
src/host/usbh.c
-include ../../rules.mk
+include ../../build_system/make/rules.mk
diff --git a/examples/dual/host_hid_to_device_cdc/only.txt b/examples/dual/host_hid_to_device_cdc/only.txt
index 6ee8e3fde..cfc87eb4e 100644
--- a/examples/dual/host_hid_to_device_cdc/only.txt
+++ b/examples/dual/host_hid_to_device_cdc/only.txt
@@ -1,3 +1,6 @@
board:mimxrt1060_evk
board:mimxrt1064_evk
+board:mcb1800
mcu:RP2040
+mcu:ra6m5
+mcu:MAX3421
diff --git a/examples/dual/host_hid_to_device_cdc/src/main.c b/examples/dual/host_hid_to_device_cdc/src/main.c
index bd7870274..96a2beff5 100644
--- a/examples/dual/host_hid_to_device_cdc/src/main.c
+++ b/examples/dual/host_hid_to_device_cdc/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -30,7 +30,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
@@ -83,6 +83,10 @@ int main(void)
tud_init(BOARD_TUD_RHPORT);
tuh_init(BOARD_TUH_RHPORT);
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
while (1)
{
tud_task(); // tinyusb device task
@@ -121,7 +125,7 @@ void tud_suspend_cb(bool remote_wakeup_en)
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = BLINK_MOUNTED;
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
// Invoked when CDC interface received data from host
diff --git a/examples/dual/host_hid_to_device_cdc/src/tusb_config.h b/examples/dual/host_hid_to_device_cdc/src/tusb_config.h
index f749bd712..8133ed418 100644
--- a/examples/dual/host_hid_to_device_cdc/src/tusb_config.h
+++ b/examples/dual/host_hid_to_device_cdc/src/tusb_config.h
@@ -84,10 +84,6 @@
#define CFG_TUH_RPI_PIO_USB 1
#endif
-
-// 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.
@@ -95,12 +91,12 @@
* - 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
+#ifndef CFG_TUD_MEM_SECTION
+#define CFG_TUD_MEM_SECTION
#endif
-#ifndef CFG_TUSB_MEM_ALIGN
-#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
+#ifndef CFG_TUD_MEM_ALIGN
+#define CFG_TUD_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
@@ -128,11 +124,19 @@
// Size of buffer to hold descriptors and other data used for enumeration
#define CFG_TUH_ENUMERATION_BUFSIZE 256
+#ifndef CFG_TUH_MEM_SECTION
+#define CFG_TUH_MEM_SECTION
+#endif
+
+#ifndef CFG_TUH_MEM_ALIGN
+#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
+#endif
+
#define CFG_TUH_HUB 1
// max device support (excluding hub device)
#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports
-#define CFG_TUH_HID 4
+#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX)
#define CFG_TUH_HID_EPIN_BUFSIZE 64
#define CFG_TUH_HID_EPOUT_BUFSIZE 64
diff --git a/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c b/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c
index 6b0a89127..293620042 100644
--- a/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c
+++ b/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,6 +23,7 @@
*
*/
+#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.
@@ -214,52 +215,64 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// 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 [] =
+char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
- "123456789012", // 3: Serials, should use chip ID
+ NULL, // 3: Serials will use unique ID if possible
"TinyUSB CDC", // 4: CDC Interface
};
-static uint16_t _desc_str[32];
+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;
- uint8_t chr_count;
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- if ( index == 0)
- {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }else
- {
- // 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
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ 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
- const char* str = string_desc_arr[index];
+ if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ const char *str = string_desc_arr[index];
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i 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));
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
diff --git a/examples/host/CMakeLists.txt b/examples/host/CMakeLists.txt
index 758973ab2..e6a2ece14 100644
--- a/examples/host/CMakeLists.txt
+++ b/examples/host/CMakeLists.txt
@@ -1,12 +1,13 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake)
-project(tinyusb_host_examples)
+project(tinyusb_host_examples C CXX ASM)
family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR})
# family_add_subdirectory will filter what to actually add based on selected FAMILY
family_add_subdirectory(bare_api)
family_add_subdirectory(cdc_msc_hid)
+family_add_subdirectory(cdc_msc_hid_freertos)
family_add_subdirectory(hid_controller)
family_add_subdirectory(msc_file_explorer)
diff --git a/examples/host/bare_api/CMakeLists.txt b/examples/host/bare_api/CMakeLists.txt
index 4879613b4..76182d6fa 100644
--- a/examples/host/bare_api/CMakeLists.txt
+++ b/examples/host/bare_api/CMakeLists.txt
@@ -1,15 +1,20 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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
@@ -22,6 +27,6 @@ target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_host_example(${PROJECT})
+# Configure compilation flags and libraries for the example without RTOS.
+# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
+family_configure_host_example(${PROJECT} noos)
diff --git a/examples/host/bare_api/Makefile b/examples/host/bare_api/Makefile
index 84555a889..0235e08c3 100644
--- a/examples/host/bare_api/Makefile
+++ b/examples/host/bare_api/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -11,14 +10,4 @@ EXAMPLE_SOURCE += \
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
-# TinyUSB Host Stack source
-SRC_C += \
- src/class/cdc/cdc_host.c \
- src/class/hid/hid_host.c \
- src/class/msc/msc_host.c \
- src/host/hub.c \
- src/host/usbh.c \
- src/portable/ohci/ohci.c \
- src/portable/nxp/lpc17_40/hcd_lpc17_40.c
-
-include ../../rules.mk
+include ../../build_system/make/rules.mk
diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt
index fa9c14857..fee10f9e2 100644
--- a/examples/host/bare_api/only.txt
+++ b/examples/host/bare_api/only.txt
@@ -1,11 +1,14 @@
+mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
-mcu:MIMXRT
+mcu:MIMXRT1XXX
mcu:MIMXRT10XX
mcu:MIMXRT11XX
mcu:RP2040
mcu:MSP432E4
mcu:RX65X
+mcu:RAXXX
+mcu:MAX3421
diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c
index 51cab2de0..670e58498 100644
--- a/examples/host/bare_api/src/main.c
+++ b/examples/host/bare_api/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -32,8 +32,9 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
+#include "class/hid/hid.h"
// English
#define LANGUAGE_ID 0x0409
@@ -67,6 +68,10 @@ int main(void)
// init host stack on configured roothub port
tuh_init(BOARD_TUH_RHPORT);
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
while (1)
{
// tinyusb host task
@@ -410,10 +415,11 @@ static int _count_utf8_bytes(const uint16_t *buf, size_t len) {
}
static void print_utf16(uint16_t *temp_buf, size_t buf_len) {
+ if ((temp_buf[0] & 0xff) == 0) return; // empty
size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
size_t utf8_len = (size_t) _count_utf8_bytes(temp_buf + 1, utf16_len);
_convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len);
((uint8_t*) temp_buf)[utf8_len] = '\0';
- printf((char*)temp_buf);
+ printf("%s", (char*)temp_buf);
}
diff --git a/examples/host/bare_api/src/tusb_config.h b/examples/host/bare_api/src/tusb_config.h
index 701aa6d90..432446e94 100644
--- a/examples/host/bare_api/src/tusb_config.h
+++ b/examples/host/bare_api/src/tusb_config.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -30,28 +30,8 @@
extern "C" {
#endif
-//--------------------------------------------------------------------+
-// Board Specific Configuration
-//--------------------------------------------------------------------+
-
-#if CFG_TUSB_MCU == OPT_MCU_RP2040
-// change to 1 if using pico-pio-usb as host controller for raspberry rp2040
-#define CFG_TUH_RPI_PIO_USB 0
-#define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB
-#endif
-
-// RHPort number used for host can be defined by board.mk, default to port 0
-#ifndef BOARD_TUH_RHPORT
-#define BOARD_TUH_RHPORT 0
-#endif
-
-// RHPort max operational speed can defined by board.mk
-#ifndef BOARD_TUH_MAX_SPEED
-#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
-#endif
-
//--------------------------------------------------------------------
-// COMMON CONFIGURATION
+// Common Configuration
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
@@ -67,12 +47,6 @@
#define CFG_TUSB_DEBUG 0
#endif
-// Enable Host stack
-#define CFG_TUH_ENABLED 1
-
-// Default is max speed that hardware controller could support with on-chip PHY
-#define CFG_TUH_MAX_SPEED BOARD_TUH_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.
@@ -80,16 +54,48 @@
* - 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
+#ifndef CFG_TUH_MEM_SECTION
+#define CFG_TUH_MEM_SECTION
#endif
-#ifndef CFG_TUSB_MEM_ALIGN
-#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
+#ifndef CFG_TUH_MEM_ALIGN
+#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
-// CONFIGURATION
+// Host Configuration
+//--------------------------------------------------------------------
+
+// Enable Host stack
+#define CFG_TUH_ENABLED 1
+
+#if CFG_TUSB_MCU == OPT_MCU_RP2040
+ // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
+ // #define CFG_TUH_MAX3421 1 // use max3421 as host controller
+
+ // host roothub port is 1 if using either pio-usb or max3421
+ #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
+ #define BOARD_TUH_RHPORT 1
+ #endif
+#endif
+
+// Default is max speed that hardware controller could support with on-chip PHY
+#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
+
+//------------------------- Board Specific --------------------------
+
+// RHPort number used for host can be defined by board.mk, default to port 0
+#ifndef BOARD_TUH_RHPORT
+#define BOARD_TUH_RHPORT 0
+#endif
+
+// RHPort max operational speed can defined by board.mk
+#ifndef BOARD_TUH_MAX_SPEED
+#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
+#endif
+
+//--------------------------------------------------------------------
+// Driver Configuration
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
@@ -100,7 +106,7 @@
// max device support (excluding hub device)
// 1 hub typically has 4 ports
-#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1)
+#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
// Max endpoint per device
#define CFG_TUH_ENDPOINT_MAX 8
diff --git a/examples/host/cdc_msc_hid/CMakeLists.txt b/examples/host/cdc_msc_hid/CMakeLists.txt
index dbba6bf44..a7c372a34 100644
--- a/examples/host/cdc_msc_hid/CMakeLists.txt
+++ b/examples/host/cdc_msc_hid/CMakeLists.txt
@@ -1,30 +1,35 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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/cdc_app.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
- )
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
+ )
# Example include
target_include_directories(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src
- )
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ )
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_host_example(${PROJECT})
+# Configure compilation flags and libraries for the example without RTOS.
+# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
+family_configure_host_example(${PROJECT} noos)
diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile
index 9adccfa3a..213c02f9c 100644
--- a/examples/host/cdc_msc_hid/Makefile
+++ b/examples/host/cdc_msc_hid/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -14,14 +13,4 @@ EXAMPLE_SOURCE = \
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
-# TinyUSB Host Stack source
-SRC_C += \
- src/class/cdc/cdc_host.c \
- src/class/hid/hid_host.c \
- src/class/msc/msc_host.c \
- src/host/hub.c \
- src/host/usbh.c \
- src/portable/ohci/ohci.c \
- src/portable/nxp/lpc17_40/hcd_lpc17_40.c
-
-include ../../rules.mk
+include ../../build_system/make/rules.mk
diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt
index fa9c14857..fee10f9e2 100644
--- a/examples/host/cdc_msc_hid/only.txt
+++ b/examples/host/cdc_msc_hid/only.txt
@@ -1,11 +1,14 @@
+mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
-mcu:MIMXRT
+mcu:MIMXRT1XXX
mcu:MIMXRT10XX
mcu:MIMXRT11XX
mcu:RP2040
mcu:MSP432E4
mcu:RX65X
+mcu:RAXXX
+mcu:MAX3421
diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c
index b1b137e0e..4a13f8b27 100644
--- a/examples/host/cdc_msc_hid/src/cdc_app.c
+++ b/examples/host/cdc_msc_hid/src/cdc_app.c
@@ -25,22 +25,13 @@
*/
#include "tusb.h"
-#include "bsp/board.h"
+#include "bsp/board_api.h"
-//--------------------------------------------------------------------+
-// MACRO TYPEDEF CONSTANT ENUM DECLARATION
-//--------------------------------------------------------------------+
-
-
-//------------- IMPLEMENTATION -------------//
-
-size_t get_console_inputs(uint8_t* buf, size_t bufsize)
-{
+size_t get_console_inputs(uint8_t* buf, size_t bufsize) {
size_t count = 0;
- while (count < bufsize)
- {
+ while (count < bufsize) {
int ch = board_getchar();
- if ( ch <= 0 ) break;
+ if (ch <= 0) break;
buf[count] = (uint8_t) ch;
count++;
@@ -49,22 +40,18 @@ size_t get_console_inputs(uint8_t* buf, size_t bufsize)
return count;
}
-void cdc_app_task(void)
-{
- uint8_t buf[64+1]; // +1 for extra null character
- uint32_t const bufsize = sizeof(buf)-1;
+void cdc_app_task(void) {
+ uint8_t buf[64 + 1]; // +1 for extra null character
+ uint32_t const bufsize = sizeof(buf) - 1;
uint32_t count = get_console_inputs(buf, bufsize);
buf[count] = 0;
// loop over all mounted interfaces
- for(uint8_t idx=0; idx cdc interfaces
- if (count)
- {
+ if (count) {
tuh_cdc_write(idx, buf, count);
tuh_cdc_write_flush(idx);
}
@@ -72,42 +59,51 @@ void cdc_app_task(void)
}
}
+//--------------------------------------------------------------------+
+// TinyUSB callbacks
+//--------------------------------------------------------------------+
+
// Invoked when received new data
-void tuh_cdc_rx_cb(uint8_t idx)
-{
- uint8_t buf[64+1]; // +1 for extra null character
- uint32_t const bufsize = sizeof(buf)-1;
+void tuh_cdc_rx_cb(uint8_t idx) {
+ uint8_t buf[64 + 1]; // +1 for extra null character
+ uint32_t const bufsize = sizeof(buf) - 1;
// forward cdc interfaces -> console
uint32_t count = tuh_cdc_read(idx, buf, bufsize);
buf[count] = 0;
- printf((char*) buf);
+ printf("%s", (char*) buf);
}
-void tuh_cdc_mount_cb(uint8_t idx)
-{
- tuh_cdc_itf_info_t itf_info = { 0 };
+// Invoked when a device with CDC interface is mounted
+// idx is index of cdc interface in the internal pool.
+void tuh_cdc_mount_cb(uint8_t idx) {
+ tuh_itf_info_t itf_info = {0};
tuh_cdc_itf_get_info(idx, &itf_info);
- printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.bInterfaceNumber);
+ printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr,
+ itf_info.desc.bInterfaceNumber);
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
- // CFG_TUH_CDC_LINE_CODING_ON_ENUM must be defined for line coding is set by tinyusb in enumeration
- // otherwise you need to call tuh_cdc_set_line_coding() first
- cdc_line_coding_t line_coding = { 0 };
- if ( tuh_cdc_get_local_line_coding(idx, &line_coding) )
- {
- printf(" Baudrate: %lu, Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits);
- printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity , line_coding.data_bits);
+ // If CFG_TUH_CDC_LINE_CODING_ON_ENUM is defined, line coding will be set by tinyusb stack
+ // while eneumerating new cdc device
+ cdc_line_coding_t line_coding = {0};
+ if (tuh_cdc_get_local_line_coding(idx, &line_coding)) {
+ printf(" Baudrate: %" PRIu32 ", Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits);
+ printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits);
}
+#else
+ // Set Line Coding upon mounted
+ cdc_line_coding_t new_line_coding = { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 };
+ tuh_cdc_set_line_coding(idx, &new_line_coding, NULL, 0);
#endif
}
-void tuh_cdc_umount_cb(uint8_t idx)
-{
- tuh_cdc_itf_info_t itf_info = { 0 };
+// Invoked when a device with CDC interface is unmounted
+void tuh_cdc_umount_cb(uint8_t idx) {
+ tuh_itf_info_t itf_info = {0};
tuh_cdc_itf_get_info(idx, &itf_info);
- printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.bInterfaceNumber);
+ printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr,
+ itf_info.desc.bInterfaceNumber);
}
diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c
index ed53c502d..f0d42a08f 100644
--- a/examples/host/cdc_msc_hid/src/hid_app.c
+++ b/examples/host/cdc_msc_hid/src/hid_app.c
@@ -23,7 +23,7 @@
*
*/
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
@@ -160,7 +160,9 @@ static void process_kbd_report(hid_keyboard_report_t const *report)
putchar(ch);
if ( ch == '\r' ) putchar('\n'); // added new line for enter key
+ #ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
fflush(stdout); // flush right away, else nanolib will wait for newline
+ #endif
}
}
// TODO example skips key released
@@ -263,7 +265,7 @@ static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t c
if (!rpt_info)
{
- printf("Couldn't find the report info for this report !\r\n");
+ printf("Couldn't find report info !\r\n");
return;
}
diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c
index b34810252..a3b80e030 100644
--- a/examples/host/cdc_msc_hid/src/main.c
+++ b/examples/host/cdc_msc_hid/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -27,20 +27,24 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
void led_blinking_task(void);
-
extern void cdc_app_task(void);
extern void hid_app_task(void);
+#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
+// API to read/rite MAX3421's register. Implemented by TinyUSB
+extern uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr);
+extern bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr);
+#endif
+
/*------------- MAIN -------------*/
-int main(void)
-{
+int main(void) {
board_init();
printf("TinyUSB Host CDC MSC HID Example\r\n");
@@ -48,8 +52,17 @@ int main(void)
// init host stack on configured roothub port
tuh_init(BOARD_TUH_RHPORT);
- while (1)
- {
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
+#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
+ // FeatherWing MAX3421E use MAX3421E's GPIO0 for VBUS enable
+ enum { IOPINS1_ADDR = 20u << 3, /* 0xA0 */ };
+ tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false);
+#endif
+
+ while (1) {
// tinyusb host task
tuh_task();
@@ -57,22 +70,18 @@ int main(void)
cdc_app_task();
hid_app_task();
}
-
- return 0;
}
//--------------------------------------------------------------------+
// TinyUSB Callbacks
//--------------------------------------------------------------------+
-void tuh_mount_cb(uint8_t dev_addr)
-{
+void tuh_mount_cb(uint8_t dev_addr) {
// application set-up
printf("A device with address %d is mounted\r\n", dev_addr);
}
-void tuh_umount_cb(uint8_t dev_addr)
-{
+void tuh_umount_cb(uint8_t dev_addr) {
// application tear-down
printf("A device with address %d is unmounted \r\n", dev_addr);
}
@@ -81,15 +90,14 @@ void tuh_umount_cb(uint8_t dev_addr)
//--------------------------------------------------------------------+
// Blinking Task
//--------------------------------------------------------------------+
-void led_blinking_task(void)
-{
+void led_blinking_task(void) {
const uint32_t interval_ms = 1000;
static uint32_t start_ms = 0;
static bool led_state = false;
// Blink every interval ms
- if ( board_millis() - start_ms < interval_ms) return; // not enough time
+ if (board_millis() - start_ms < interval_ms) return; // not enough time
start_ms += interval_ms;
board_led_write(led_state);
diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c
index 797d55f8a..1d7e18e6e 100644
--- a/examples/host/cdc_msc_hid/src/msc_app.c
+++ b/examples/host/cdc_msc_hid/src/msc_app.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -48,8 +48,8 @@ bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_da
uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun);
uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun);
- printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size));
- printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size);
+ printf("Disk Size: %" PRIu32 " MB\r\n", block_count / ((1024*1024)/block_size));
+ printf("Block Count = %" PRIu32 ", Block Size: %" PRIu32 "\r\n", block_count, block_size);
return true;
}
@@ -68,4 +68,3 @@ void tuh_msc_umount_cb(uint8_t dev_addr)
(void) dev_addr;
printf("A MassStorage device is unmounted\r\n");
}
-
diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h
index 139a921d1..a59a0ffb9 100644
--- a/examples/host/cdc_msc_hid/src/tusb_config.h
+++ b/examples/host/cdc_msc_hid/src/tusb_config.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -30,28 +30,8 @@
extern "C" {
#endif
-//--------------------------------------------------------------------+
-// Board Specific Configuration
-//--------------------------------------------------------------------+
-
-#if CFG_TUSB_MCU == OPT_MCU_RP2040
-// change to 1 if using pico-pio-usb as host controller for raspberry rp2040
-#define CFG_TUH_RPI_PIO_USB 0
-#define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB
-#endif
-
-// RHPort number used for host can be defined by board.mk, default to port 0
-#ifndef BOARD_TUH_RHPORT
-#define BOARD_TUH_RHPORT 0
-#endif
-
-// RHPort max operational speed can defined by board.mk
-#ifndef BOARD_TUH_MAX_SPEED
-#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
-#endif
-
//--------------------------------------------------------------------
-// COMMON CONFIGURATION
+// Common Configuration
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
@@ -67,12 +47,6 @@
#define CFG_TUSB_DEBUG 0
#endif
-// Enable Host stack
-#define CFG_TUH_ENABLED 1
-
-// Default is max speed that hardware controller could support with on-chip PHY
-#define CFG_TUH_MAX_SPEED BOARD_TUH_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.
@@ -80,29 +54,64 @@
* - 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
+#ifndef CFG_TUH_MEM_SECTION
+#define CFG_TUH_MEM_SECTION
#endif
-#ifndef CFG_TUSB_MEM_ALIGN
-#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
+#ifndef CFG_TUH_MEM_ALIGN
+#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
-// CONFIGURATION
+// Host Configuration
+//--------------------------------------------------------------------
+
+// Enable Host stack
+#define CFG_TUH_ENABLED 1
+
+#if CFG_TUSB_MCU == OPT_MCU_RP2040
+ // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
+ // #define CFG_TUH_MAX3421 1 // use max3421 as host controller
+
+ // host roothub port is 1 if using either pio-usb or max3421
+ #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
+ #define BOARD_TUH_RHPORT 1
+ #endif
+#endif
+
+// Default is max speed that hardware controller could support with on-chip PHY
+#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
+
+//------------------------- Board Specific --------------------------
+
+// RHPort number used for host can be defined by board.mk, default to port 0
+#ifndef BOARD_TUH_RHPORT
+#define BOARD_TUH_RHPORT 0
+#endif
+
+// RHPort max operational speed can defined by board.mk
+#ifndef BOARD_TUH_MAX_SPEED
+#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
+#endif
+
+//--------------------------------------------------------------------
+// Driver Configuration
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
#define CFG_TUH_ENUMERATION_BUFSIZE 256
#define CFG_TUH_HUB 1 // number of supported hubs
-#define CFG_TUH_CDC 1
-#define CFG_TUH_HID 4 // typical keyboard + mouse device can have 3-4 HID interfaces
+#define CFG_TUH_CDC 1 // CDC ACM
+#define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API
+#define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API
+#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API
+#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces
#define CFG_TUH_MSC 1
#define CFG_TUH_VENDOR 0
-// max device support (excluding hub device)
-#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports
+// max device support (excluding hub device): 1 hub typically has 4 ports
+#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
//------------- HID -------------//
#define CFG_TUH_HID_EPIN_BUFSIZE 64
@@ -116,7 +125,7 @@
// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t
// bit rate = 115200, 1 stop bit, no parity, 8 bit data width
-#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
+#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
#ifdef __cplusplus
diff --git a/examples/host/cdc_msc_hid_freertos/CMakeLists.txt b/examples/host/cdc_msc_hid_freertos/CMakeLists.txt
new file mode 100644
index 000000000..2e95a18e0
--- /dev/null
+++ b/examples/host/cdc_msc_hid_freertos/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 3.17)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
+
+# gets PROJECT name for the example (e.g. -)
+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/cdc_app.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/freertos_hook.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.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_host_example(${PROJECT} freertos)
diff --git a/examples/host/cdc_msc_hid_freertos/Makefile b/examples/host/cdc_msc_hid_freertos/Makefile
new file mode 100644
index 000000000..bf4725f47
--- /dev/null
+++ b/examples/host/cdc_msc_hid_freertos/Makefile
@@ -0,0 +1,34 @@
+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/cdc_app.c \
+ src/freertos_hook.c \
+ src/hid_app.c \
+ src/main.c \
+ src/msc_app.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))
+
+include ../../build_system/make/rules.mk
diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt
new file mode 100644
index 000000000..81d993ffa
--- /dev/null
+++ b/examples/host/cdc_msc_hid_freertos/only.txt
@@ -0,0 +1,12 @@
+mcu:LPC175X_6X
+mcu:LPC177X_8X
+mcu:LPC18XX
+mcu:LPC40XX
+mcu:LPC43XX
+mcu:MIMXRT1XXX
+mcu:MIMXRT10XX
+mcu:MIMXRT11XX
+mcu:MSP432E4
+mcu:RX65X
+mcu:RAXXX
+mcu:MAX3421
diff --git a/examples/host/cdc_msc_hid_freertos/skip.txt b/examples/host/cdc_msc_hid_freertos/skip.txt
new file mode 100644
index 000000000..2ba4438fd
--- /dev/null
+++ b/examples/host/cdc_msc_hid_freertos/skip.txt
@@ -0,0 +1 @@
+mcu:RP2040
diff --git a/examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt b/examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt
new file mode 100644
index 000000000..6f057c106
--- /dev/null
+++ b/examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt
@@ -0,0 +1,6 @@
+# This file is for ESP-IDF only
+idf_component_register(SRCS "cdc_app.c" "hid_app.c" "main.c" "msc_app.c"
+ INCLUDE_DIRS "."
+ REQUIRES boards tinyusb_src)
+
+target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=format)
diff --git a/examples/host/cdc_msc_hid_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/host/cdc_msc_hid_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
new file mode 100644
index 000000000..bd754518d
--- /dev/null
+++ b/examples/host/cdc_msc_hid_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
@@ -0,0 +1,199 @@
+/*
+ * 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
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
+
+// TODO fix later
+// FIXME cause redundant-decls warnings
+#if CFG_TUSB_MCU == OPT_MCU_MM32F327X
+ extern u32 SystemCoreClock;
+#else
+ extern uint32_t SystemCoreClock;
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#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< cdc interfaces
+ tuh_cdc_write(idx, buf, count);
+ tuh_cdc_write_flush(idx);
+ }
+ }
+ }
+
+ vTaskDelay(1);
+ }
+}
+
+//--------------------------------------------------------------------+
+// TinyUSB Callbacks
+//--------------------------------------------------------------------+
+
+// Invoked when received new data
+void tuh_cdc_rx_cb(uint8_t idx) {
+ uint8_t buf[64 + 1]; // +1 for extra null character
+ uint32_t const bufsize = sizeof(buf) - 1;
+
+ // forward cdc interfaces -> console
+ uint32_t count = tuh_cdc_read(idx, buf, bufsize);
+ buf[count] = 0;
+
+ printf("%s", (char *) buf);
+}
+
+void tuh_cdc_mount_cb(uint8_t idx) {
+ tuh_itf_info_t itf_info = { 0 };
+ tuh_cdc_itf_get_info(idx, &itf_info);
+
+ printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber);
+
+#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
+ // CFG_TUH_CDC_LINE_CODING_ON_ENUM must be defined for line coding is set by tinyusb in enumeration
+ // otherwise you need to call tuh_cdc_set_line_coding() first
+ cdc_line_coding_t line_coding = { 0 };
+ if (tuh_cdc_get_local_line_coding(idx, &line_coding)) {
+ printf(" Baudrate: %" PRIu32 ", Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits);
+ printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits);
+ }
+#endif
+}
+
+void tuh_cdc_umount_cb(uint8_t idx) {
+ tuh_itf_info_t itf_info = { 0 };
+ tuh_cdc_itf_get_info(idx, &itf_info);
+
+ printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber);
+}
diff --git a/examples/host/cdc_msc_hid_freertos/src/freertos_hook.c b/examples/host/cdc_msc_hid_freertos/src/freertos_hook.c
new file mode 100644
index 000000000..07d159fd5
--- /dev/null
+++ b/examples/host/cdc_msc_hid_freertos/src/freertos_hook.c
@@ -0,0 +1,111 @@
+/*
+ * 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 */
+ SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1);
+ MSTP(CMT0) = 0;
+ SYSTEM.PRCR.WORD = (0xA5u<<8);
+
+ 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/host/cdc_msc_hid_freertos/src/hid_app.c b/examples/host/cdc_msc_hid_freertos/src/hid_app.c
new file mode 100644
index 000000000..9ea5c1be0
--- /dev/null
+++ b/examples/host/cdc_msc_hid_freertos/src/hid_app.c
@@ -0,0 +1,267 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021, 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"
+
+//--------------------------------------------------------------------+
+// MACRO TYPEDEF CONSTANT ENUM DECLARATION
+//--------------------------------------------------------------------+
+
+// If your host terminal support ansi escape code such as TeraTerm
+// it can be use to simulate mouse cursor movement within terminal
+#define USE_ANSI_ESCAPE 0
+
+#define MAX_REPORT 4
+
+static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
+
+// Each HID instance can has multiple reports
+static struct {
+ uint8_t report_count;
+ tuh_hid_report_info_t report_info[MAX_REPORT];
+} hid_info[CFG_TUH_HID];
+
+static void process_kbd_report(hid_keyboard_report_t const *report);
+static void process_mouse_report(hid_mouse_report_t const *report);
+static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len);
+
+void hid_app_init(void) {
+ // nothing to do
+}
+
+//--------------------------------------------------------------------+
+// TinyUSB Callbacks
+//--------------------------------------------------------------------+
+
+// Invoked when device with hid interface is mounted
+// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
+// can be used to parse common/simple enough descriptor.
+// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
+// therefore report_desc = NULL, desc_len = 0
+void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) {
+ printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
+
+ // Interface protocol (hid_interface_protocol_enum_t)
+ const char *protocol_str[] = { "None", "Keyboard", "Mouse" };
+ uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
+
+ printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]);
+
+ // By default host stack will use activate boot protocol on supported interface.
+ // Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser)
+ if (itf_protocol == HID_ITF_PROTOCOL_NONE) {
+ hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT,
+ desc_report, desc_len);
+ printf("HID has %u reports \r\n", hid_info[instance].report_count);
+ }
+
+ // request to receive report
+ // tuh_hid_report_received_cb() will be invoked when report is available
+ if (!tuh_hid_receive_report(dev_addr, instance)) {
+ printf("Error: cannot request to receive report\r\n");
+ }
+}
+
+// Invoked when device with hid interface is un-mounted
+void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
+ printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
+}
+
+// Invoked when received report from device via interrupt endpoint
+void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
+ uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
+
+ switch (itf_protocol) {
+ case HID_ITF_PROTOCOL_KEYBOARD:
+ TU_LOG2("HID receive boot keyboard report\r\n");
+ process_kbd_report((hid_keyboard_report_t const *) report);
+ break;
+
+ case HID_ITF_PROTOCOL_MOUSE:
+ TU_LOG2("HID receive boot mouse report\r\n");
+ process_mouse_report((hid_mouse_report_t const *) report);
+ break;
+
+ default:
+ // Generic report requires matching ReportID and contents with previous parsed report info
+ process_generic_report(dev_addr, instance, report, len);
+ break;
+ }
+
+ // continue to request to receive report
+ if (!tuh_hid_receive_report(dev_addr, instance)) {
+ printf("Error: cannot request to receive report\r\n");
+ }
+}
+
+//--------------------------------------------------------------------+
+// Keyboard
+//--------------------------------------------------------------------+
+
+// look up new key in previous keys
+static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode) {
+ for (uint8_t i = 0; i < 6; i++) {
+ if (report->keycode[i] == keycode) return true;
+ }
+
+ return false;
+}
+
+static void process_kbd_report(hid_keyboard_report_t const *report) {
+ static hid_keyboard_report_t prev_report = { 0, 0, { 0 } }; // previous report to check key released
+
+ //------------- example code ignore control (non-printable) key affects -------------//
+ for (uint8_t i = 0; i < 6; i++) {
+ if (report->keycode[i]) {
+ if (find_key_in_report(&prev_report, report->keycode[i])) {
+ // exist in previous report means the current key is holding
+ } else {
+ // not existed in previous report means the current key is pressed
+ bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
+ uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0];
+ putchar(ch);
+ if (ch == '\r') putchar('\n'); // added new line for enter key
+
+ #ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
+ fflush(stdout); // flush right away, else nanolib will wait for newline
+ #endif
+ }
+ }
+ // TODO example skips key released
+ }
+
+ prev_report = *report;
+}
+
+//--------------------------------------------------------------------+
+// Mouse
+//--------------------------------------------------------------------+
+
+void cursor_movement(int8_t x, int8_t y, int8_t wheel) {
+#if USE_ANSI_ESCAPE
+ // Move X using ansi escape
+ if ( x < 0) {
+ printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left
+ }else if ( x > 0) {
+ printf(ANSI_CURSOR_FORWARD(%d), x); // move right
+ }
+
+ // Move Y using ansi escape
+ if ( y < 0) {
+ printf(ANSI_CURSOR_UP(%d), (-y)); // move up
+ }else if ( y > 0) {
+ printf(ANSI_CURSOR_DOWN(%d), y); // move down
+ }
+
+ // Scroll using ansi escape
+ if (wheel < 0) {
+ printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up
+ }else if (wheel > 0) {
+ printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down
+ }
+
+ printf("\r\n");
+#else
+ printf("(%d %d %d)\r\n", x, y, wheel);
+#endif
+}
+
+static void process_mouse_report(hid_mouse_report_t const *report) {
+ static hid_mouse_report_t prev_report = { 0 };
+
+ //------------- button state -------------//
+ uint8_t button_changed_mask = report->buttons ^ prev_report.buttons;
+ if (button_changed_mask & report->buttons) {
+ printf(" %c%c%c ",
+ report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-',
+ report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-',
+ report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-');
+ }
+
+ //------------- cursor movement -------------//
+ cursor_movement(report->x, report->y, report->wheel);
+}
+
+//--------------------------------------------------------------------+
+// Generic Report
+//--------------------------------------------------------------------+
+static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
+ (void) dev_addr;
+
+ uint8_t const rpt_count = hid_info[instance].report_count;
+ tuh_hid_report_info_t *rpt_info_arr = hid_info[instance].report_info;
+ tuh_hid_report_info_t *rpt_info = NULL;
+
+ if (rpt_count == 1 && rpt_info_arr[0].report_id == 0) {
+ // Simple report without report ID as 1st byte
+ rpt_info = &rpt_info_arr[0];
+ } else {
+ // Composite report, 1st byte is report ID, data starts from 2nd byte
+ uint8_t const rpt_id = report[0];
+
+ // Find report id in the array
+ for (uint8_t i = 0; i < rpt_count; i++) {
+ if (rpt_id == rpt_info_arr[i].report_id) {
+ rpt_info = &rpt_info_arr[i];
+ break;
+ }
+ }
+
+ report++;
+ len--;
+ }
+
+ if (!rpt_info) {
+ printf("Couldn't find report info !\r\n");
+ return;
+ }
+
+ // For complete list of Usage Page & Usage checkout src/class/hid/hid.h. For examples:
+ // - Keyboard : Desktop, Keyboard
+ // - Mouse : Desktop, Mouse
+ // - Gamepad : Desktop, Gamepad
+ // - Consumer Control (Media Key) : Consumer, Consumer Control
+ // - System Control (Power key) : Desktop, System Control
+ // - Generic (vendor) : 0xFFxx, xx
+ if (rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP) {
+ switch (rpt_info->usage) {
+ case HID_USAGE_DESKTOP_KEYBOARD:
+ TU_LOG1("HID receive keyboard report\r\n");
+ // Assume keyboard follow boot report layout
+ process_kbd_report((hid_keyboard_report_t const *) report);
+ break;
+
+ case HID_USAGE_DESKTOP_MOUSE:
+ TU_LOG1("HID receive mouse report\r\n");
+ // Assume mouse follow boot report layout
+ process_mouse_report((hid_mouse_report_t const *) report);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
diff --git a/examples/host/cdc_msc_hid_freertos/src/main.c b/examples/host/cdc_msc_hid_freertos/src/main.c
new file mode 100644
index 000000000..fa799aede
--- /dev/null
+++ b/examples/host/cdc_msc_hid_freertos/src/main.c
@@ -0,0 +1,180 @@
+/*
+ * 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
+#include
+
+#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 USBH_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 USBH_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
+#endif
+
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF 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 timer & task
+#if configSUPPORT_STATIC_ALLOCATION
+StaticTimer_t blinky_tmdef;
+
+StackType_t usb_host_stack[USBH_STACK_SIZE];
+StaticTask_t usb_host_taskdef;
+#endif
+
+TimerHandle_t blinky_tm;
+
+static void led_blinky_cb(TimerHandle_t xTimer);
+static void usb_host_task(void* param);
+
+extern void cdc_app_init(void);
+extern void hid_app_init(void);
+extern void msc_app_init(void);
+
+#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
+// API to read/rite MAX3421's register. Implemented by TinyUSB
+extern uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr);
+extern bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr);
+#endif
+
+/*------------- MAIN -------------*/
+int main(void) {
+ board_init();
+
+ printf("TinyUSB Host CDC MSC HID with FreeRTOS Example\r\n");
+
+ // Create soft timer for blinky, task for tinyusb stack
+#if configSUPPORT_STATIC_ALLOCATION
+ blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef);
+ xTaskCreateStatic(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_host_stack, &usb_host_taskdef);
+#else
+ blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb);
+ xTaskCreate(usb_host_task, "usbd", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL);
+#endif
+
+ xTimerStart(blinky_tm, 0);
+
+ // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
+#if !TUP_MCU_ESPRESSIF
+ vTaskStartScheduler();
+#endif
+
+ return 0;
+}
+
+#if TUP_MCU_ESPRESSIF
+void app_main(void) {
+ main();
+}
+#endif
+
+// USB Host task
+// This top level thread process all usb events and invoke callbacks
+static void usb_host_task(void *param) {
+ (void) param;
+
+ // init host stack on configured roothub port
+ if (!tuh_init(BOARD_TUH_RHPORT)) {
+ printf("Failed to init USB Host Stack\r\n");
+ vTaskSuspend(NULL);
+ }
+
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
+#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
+ // FeatherWing MAX3421E use MAX3421E's GPIO0 for VBUS enable
+ enum { IOPINS1_ADDR = 20u << 3, /* 0xA0 */ };
+ tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false);
+#endif
+
+ cdc_app_init();
+ hid_app_init();
+ msc_app_init();
+
+ // RTOS forever loop
+ while (1) {
+ // put this thread to waiting state until there is new events
+ tuh_task();
+
+ // following code only run if tuh_task() process at least 1 event
+ }
+}
+
+//--------------------------------------------------------------------+
+// TinyUSB Callbacks
+//--------------------------------------------------------------------+
+
+void tuh_mount_cb(uint8_t dev_addr) {
+ // application set-up
+ printf("A device with address %d is mounted\r\n", dev_addr);
+}
+
+void tuh_umount_cb(uint8_t dev_addr) {
+ // application tear-down
+ printf("A device with address %d is unmounted \r\n", dev_addr);
+}
+
+//--------------------------------------------------------------------+
+// BLINKING TASK
+//--------------------------------------------------------------------+
+static void led_blinky_cb(TimerHandle_t xTimer) {
+ (void) xTimer;
+ static bool led_state = false;
+
+ board_led_write(led_state);
+ led_state = 1 - led_state; // toggle
+}
diff --git a/examples/host/cdc_msc_hid_freertos/src/msc_app.c b/examples/host/cdc_msc_hid_freertos/src/msc_app.c
new file mode 100644
index 000000000..9ffd5d965
--- /dev/null
+++ b/examples/host/cdc_msc_hid_freertos/src/msc_app.c
@@ -0,0 +1,67 @@
+/*
+ * 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 "tusb.h"
+
+static scsi_inquiry_resp_t inquiry_resp;
+
+void msc_app_init(void) {
+ // nothing to do
+}
+
+bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data) {
+ msc_cbw_t const *cbw = cb_data->cbw;
+ msc_csw_t const *csw = cb_data->csw;
+
+ if (csw->status != 0) {
+ printf("Inquiry failed\r\n");
+ return false;
+ }
+
+ // Print out Vendor ID, Product ID and Rev
+ printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev);
+
+ // Get capacity of device
+ uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun);
+ uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun);
+
+ printf("Disk Size: %" PRIu32 " MB\r\n", block_count / ((1024 * 1024) / block_size));
+ printf("Block Count = %" PRIu32 ", Block Size: %" PRIu32 "\r\n", block_count, block_size);
+
+ return true;
+}
+
+//------------- IMPLEMENTATION -------------//
+void tuh_msc_mount_cb(uint8_t dev_addr) {
+ printf("A MassStorage device is mounted\r\n");
+
+ uint8_t const lun = 0;
+ tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb, 0);
+}
+
+void tuh_msc_umount_cb(uint8_t dev_addr) {
+ (void) dev_addr;
+ printf("A MassStorage device is unmounted\r\n");
+}
diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h
new file mode 100644
index 000000000..0aab2cd2f
--- /dev/null
+++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h
@@ -0,0 +1,140 @@
+/*
+ * 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
+
+//--------------------------------------------------------------------
+// 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_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
+
+/* 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_TUH_MEM_SECTION
+#define CFG_TUH_MEM_SECTION
+#endif
+
+#ifndef CFG_TUH_MEM_ALIGN
+#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
+#endif
+
+//--------------------------------------------------------------------
+// Host Configuration
+//--------------------------------------------------------------------
+
+// Enable Host stack
+#define CFG_TUH_ENABLED 1
+
+#if CFG_TUSB_MCU == OPT_MCU_RP2040
+ // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
+ // #define CFG_TUH_MAX3421 1 // use max3421 as host controller
+
+ // host roothub port is 1 if using either pio-usb or max3421
+ #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
+ #define BOARD_TUH_RHPORT 1
+ #endif
+#endif
+
+// Default is max speed that hardware controller could support with on-chip PHY
+#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
+
+//------------------------- Board Specific --------------------------
+
+// RHPort number used for host can be defined by board.mk, default to port 0
+#ifndef BOARD_TUH_RHPORT
+#define BOARD_TUH_RHPORT 0
+#endif
+
+// RHPort max operational speed can defined by board.mk
+#ifndef BOARD_TUH_MAX_SPEED
+#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
+#endif
+
+//--------------------------------------------------------------------
+// Driver Configuration
+//--------------------------------------------------------------------
+
+// Size of buffer to hold descriptors and other data used for enumeration
+#define CFG_TUH_ENUMERATION_BUFSIZE 256
+
+#define CFG_TUH_HUB 1 // number of supported hubs
+#define CFG_TUH_CDC 1 // CDC ACM
+#define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API
+#define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API
+#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API
+#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces
+#define CFG_TUH_MSC 1
+#define CFG_TUH_VENDOR 0
+
+// max device support (excluding hub device): 1 hub typically has 4 ports
+#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
+
+//------------- HID -------------//
+#define CFG_TUH_HID_EPIN_BUFSIZE 64
+#define CFG_TUH_HID_EPOUT_BUFSIZE 64
+
+//------------- CDC -------------//
+
+// Set Line Control state on enumeration/mounted:
+// DTR ( bit 0), RTS (bit 1)
+#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM 0x03
+
+// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t
+// bit rate = 115200, 1 stop bit, no parity, 8 bit data width
+#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_CONFIG_H_ */
diff --git a/examples/host/hid_controller/CMakeLists.txt b/examples/host/hid_controller/CMakeLists.txt
index aa50b5a52..c1b500dd8 100644
--- a/examples/host/hid_controller/CMakeLists.txt
+++ b/examples/host/hid_controller/CMakeLists.txt
@@ -1,28 +1,33 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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/hid_app.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
- )
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+ )
# Example include
target_include_directories(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src
- )
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ )
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_host_example(${PROJECT})
+# Configure compilation flags and libraries for the example without RTOS.
+# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
+family_configure_host_example(${PROJECT} noos)
diff --git a/examples/host/hid_controller/Makefile b/examples/host/hid_controller/Makefile
index e7fbd741f..1377f1f90 100644
--- a/examples/host/hid_controller/Makefile
+++ b/examples/host/hid_controller/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
INC += \
src \
@@ -12,14 +11,4 @@ EXAMPLE_SOURCE += \
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
-# TinyUSB Host Stack source
-SRC_C += \
- src/class/cdc/cdc_host.c \
- src/class/hid/hid_host.c \
- src/class/msc/msc_host.c \
- src/host/hub.c \
- src/host/usbh.c \
- src/portable/ohci/ohci.c \
- src/portable/nxp/lpc17_40/hcd_lpc17_40.c
-
-include ../../rules.mk
+include ../../build_system/make/rules.mk
diff --git a/examples/host/hid_controller/only.txt b/examples/host/hid_controller/only.txt
index fa9c14857..fee10f9e2 100644
--- a/examples/host/hid_controller/only.txt
+++ b/examples/host/hid_controller/only.txt
@@ -1,11 +1,14 @@
+mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
-mcu:MIMXRT
+mcu:MIMXRT1XXX
mcu:MIMXRT10XX
mcu:MIMXRT11XX
mcu:RP2040
mcu:MSP432E4
mcu:RX65X
+mcu:RAXXX
+mcu:MAX3421
diff --git a/examples/host/hid_controller/src/hid_app.c b/examples/host/hid_controller/src/hid_app.c
index 75c91400e..bff830ca2 100644
--- a/examples/host/hid_controller/src/hid_app.c
+++ b/examples/host/hid_controller/src/hid_app.c
@@ -23,7 +23,7 @@
*
*/
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
/* From https://www.kernel.org/doc/html/latest/input/gamepad.html
@@ -91,9 +91,8 @@ typedef struct TU_ATTR_PACKED
uint8_t counter : 6; // +1 each report
};
- // comment out since not used by this example
- // uint8_t l2_trigger; // 0 released, 0xff fully pressed
- // uint8_t r2_trigger; // as above
+ uint8_t l2_trigger; // 0 released, 0xff fully pressed
+ uint8_t r2_trigger; // as above
// uint16_t timestamp;
// uint8_t battery;
@@ -105,15 +104,54 @@ typedef struct TU_ATTR_PACKED
} sony_ds4_report_t;
+typedef struct TU_ATTR_PACKED {
+ // First 16 bits set what data is pertinent in this structure (1 = set; 0 = not set)
+ uint8_t set_rumble : 1;
+ uint8_t set_led : 1;
+ uint8_t set_led_blink : 1;
+ uint8_t set_ext_write : 1;
+ uint8_t set_left_volume : 1;
+ uint8_t set_right_volume : 1;
+ uint8_t set_mic_volume : 1;
+ uint8_t set_speaker_volume : 1;
+ uint8_t set_flags2;
+
+ uint8_t reserved;
+
+ uint8_t motor_right;
+ uint8_t motor_left;
+
+ uint8_t lightbar_red;
+ uint8_t lightbar_green;
+ uint8_t lightbar_blue;
+ uint8_t lightbar_blink_on;
+ uint8_t lightbar_blink_off;
+
+ uint8_t ext_data[8];
+
+ uint8_t volume_left;
+ uint8_t volume_right;
+ uint8_t volume_mic;
+ uint8_t volume_speaker;
+
+ uint8_t other[9];
+} sony_ds4_output_report_t;
+
+static bool ds4_mounted = false;
+static uint8_t ds4_dev_addr = 0;
+static uint8_t ds4_instance = 0;
+static uint8_t motor_left = 0;
+static uint8_t motor_right = 0;
+
// check if device is Sony DualShock 4
static inline bool is_sony_ds4(uint8_t dev_addr)
{
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);
- return ( (vid == 0x054c && (pid == 0x09cc || pid == 0x05c4)) // Sony DualShock4
- || (vid == 0x0f0d && pid == 0x005e) // Hori FC4
- || (vid == 0x0f0d && pid == 0x00ee) // Hori PS4 Mini (PS4-099U)
+ return ( (vid == 0x054c && (pid == 0x09cc || pid == 0x05c4)) // Sony DualShock4
+ || (vid == 0x0f0d && pid == 0x005e) // Hori FC4
+ || (vid == 0x0f0d && pid == 0x00ee) // Hori PS4 Mini (PS4-099U)
|| (vid == 0x1f4f && pid == 0x1002) // ASW GG xrd controller
);
}
@@ -124,7 +162,23 @@ static inline bool is_sony_ds4(uint8_t dev_addr)
void hid_app_task(void)
{
- // nothing to do
+ if (ds4_mounted)
+ {
+ const uint32_t interval_ms = 200;
+ static uint32_t start_ms = 0;
+
+ uint32_t current_time_ms = board_millis();
+ if ( current_time_ms - start_ms >= interval_ms)
+ {
+ start_ms = current_time_ms;
+
+ sony_ds4_output_report_t output_report = {0};
+ output_report.set_rumble = 1;
+ output_report.motor_left = motor_left;
+ output_report.motor_right = motor_right;
+ tuh_hid_send_report(ds4_dev_addr, ds4_instance, 5, &output_report, sizeof(output_report));
+ }
+ }
}
//--------------------------------------------------------------------+
@@ -149,6 +203,14 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re
// Sony DualShock 4 [CUH-ZCT2x]
if ( is_sony_ds4(dev_addr) )
{
+ if (!ds4_mounted)
+ {
+ ds4_dev_addr = dev_addr;
+ ds4_instance = instance;
+ motor_left = 0;
+ motor_right = 0;
+ ds4_mounted = true;
+ }
// request to receive report
// tuh_hid_report_received_cb() will be invoked when report is available
if ( !tuh_hid_receive_report(dev_addr, instance) )
@@ -162,6 +224,10 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
{
printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
+ if (ds4_mounted && ds4_dev_addr == dev_addr && ds4_instance == instance)
+ {
+ ds4_mounted = false;
+ }
}
// check if different than 2
@@ -179,8 +245,8 @@ bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2)
result = diff_than_2(rpt1->x, rpt2->x) || diff_than_2(rpt1->y , rpt2->y ) ||
diff_than_2(rpt1->z, rpt2->z) || diff_than_2(rpt1->rz, rpt2->rz);
- // check the reset with mem compare
- result |= memcmp(&rpt1->rz + 1, &rpt2->rz + 1, sizeof(sony_ds4_report_t)-4);
+ // check the rest with mem compare
+ result |= memcmp(&rpt1->rz + 1, &rpt2->rz + 1, sizeof(sony_ds4_report_t)-6);
return result;
}
@@ -234,6 +300,10 @@ void process_sony_ds4(uint8_t const* report, uint16_t len)
printf("\r\n");
}
+ // The left and right triggers control the intensity of the left and right rumble motors
+ motor_left = ds4_report.l2_trigger;
+ motor_right = ds4_report.r2_trigger;
+
prev_report = ds4_report;
}
}
diff --git a/examples/host/hid_controller/src/main.c b/examples/host/hid_controller/src/main.c
index 299a3ff10..05a5ae176 100644
--- a/examples/host/hid_controller/src/main.c
+++ b/examples/host/hid_controller/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -32,7 +32,7 @@
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
@@ -54,6 +54,10 @@ int main(void)
// init host stack on configured roothub port
tuh_init(BOARD_TUH_RHPORT);
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
while (1)
{
// tinyusb host task
@@ -68,8 +72,6 @@ int main(void)
hid_app_task();
#endif
}
-
- return 0;
}
//--------------------------------------------------------------------+
diff --git a/examples/host/hid_controller/src/tusb_config.h b/examples/host/hid_controller/src/tusb_config.h
index e6d6f873d..3ac591d8f 100644
--- a/examples/host/hid_controller/src/tusb_config.h
+++ b/examples/host/hid_controller/src/tusb_config.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -30,28 +30,8 @@
extern "C" {
#endif
-//--------------------------------------------------------------------+
-// Board Specific Configuration
-//--------------------------------------------------------------------+
-
- #if CFG_TUSB_MCU == OPT_MCU_RP2040
-// change to 1 if using pico-pio-usb as host controller for raspberry rp2040
-#define CFG_TUH_RPI_PIO_USB 0
-#define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB
-#endif
-
-// RHPort number used for host can be defined by board.mk, default to port 0
-#ifndef BOARD_TUH_RHPORT
-#define BOARD_TUH_RHPORT 0
-#endif
-
-// RHPort max operational speed can defined by board.mk
-#ifndef BOARD_TUH_MAX_SPEED
-#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
-#endif
-
//--------------------------------------------------------------------
-// COMMON CONFIGURATION
+// Common Configuration
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
@@ -67,12 +47,6 @@
#define CFG_TUSB_DEBUG 0
#endif
-// Enable Host stack
-#define CFG_TUH_ENABLED 1
-
-// Default is max speed that hardware controller could support with on-chip PHY
-#define CFG_TUH_MAX_SPEED BOARD_TUH_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.
@@ -80,16 +54,48 @@
* - 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
+#ifndef CFG_TUH_MEM_SECTION
+#define CFG_TUH_MEM_SECTION
#endif
-#ifndef CFG_TUSB_MEM_ALIGN
-#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
+#ifndef CFG_TUH_MEM_ALIGN
+#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
-// CONFIGURATION
+// Host Configuration
+//--------------------------------------------------------------------
+
+// Enable Host stack
+#define CFG_TUH_ENABLED 1
+
+#if CFG_TUSB_MCU == OPT_MCU_RP2040
+ // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
+ // #define CFG_TUH_MAX3421 1 // use max3421 as host controller
+
+ // host roothub port is 1 if using either pio-usb or max3421
+ #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
+ #define BOARD_TUH_RHPORT 1
+ #endif
+#endif
+
+// Default is max speed that hardware controller could support with on-chip PHY
+#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
+
+//------------------------- Board Specific --------------------------
+
+// RHPort number used for host can be defined by board.mk, default to port 0
+#ifndef BOARD_TUH_RHPORT
+#define BOARD_TUH_RHPORT 0
+#endif
+
+// RHPort max operational speed can defined by board.mk
+#ifndef BOARD_TUH_MAX_SPEED
+#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
+#endif
+
+//--------------------------------------------------------------------
+// Driver Configuration
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
@@ -97,13 +103,12 @@
#define CFG_TUH_HUB 0
#define CFG_TUH_CDC 0
-#define CFG_TUH_HID 4 // typical keyboard + mouse device can have 3-4 HID interfaces
+#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces
#define CFG_TUH_MSC 0
#define CFG_TUH_VENDOR 0
-// max device support (excluding hub device)
-// 1 hub typically has 4 ports
-#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1)
+// max device support (excluding hub device): 1 hub typically has 4 ports
+#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
//------------- HID -------------//
diff --git a/examples/host/msc_file_explorer/CMakeLists.txt b/examples/host/msc_file_explorer/CMakeLists.txt
index 2c06eafee..1a57c7466 100644
--- a/examples/host/msc_file_explorer/CMakeLists.txt
+++ b/examples/host/msc_file_explorer/CMakeLists.txt
@@ -1,34 +1,47 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-project(${PROJECT})
+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/main.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
- ${TOP}/lib/fatfs/source/ff.c
- ${TOP}/lib/fatfs/source/ffsystem.c
- ${TOP}/lib/fatfs/source/ffunicode.c
- )
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
+ ${TOP}/lib/fatfs/source/ff.c
+ ${TOP}/lib/fatfs/source/ffsystem.c
+ ${TOP}/lib/fatfs/source/ffunicode.c
+ )
+
+# Suppress warnings on fatfs
+if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
+ set_source_files_properties(
+ ${TOP}/lib/fatfs/source/ff.c
+ PROPERTIES
+ COMPILE_FLAGS "-Wno-conversion -Wno-cast-qual"
+ )
+endif ()
# Example include
target_include_directories(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src
- ${TOP}/lib/fatfs/source
- ${TOP}/lib/embedded-cli
- )
-
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_host_example(${PROJECT})
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ ${TOP}/lib/fatfs/source
+ ${TOP}/lib/embedded-cli
+ )
+# Configure compilation flags and libraries for the example without RTOS.
+# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
+family_configure_host_example(${PROJECT} noos)
diff --git a/examples/host/msc_file_explorer/Makefile b/examples/host/msc_file_explorer/Makefile
index de2f9c01c..c7d6a7cae 100644
--- a/examples/host/msc_file_explorer/Makefile
+++ b/examples/host/msc_file_explorer/Makefile
@@ -1,5 +1,4 @@
-include ../../../tools/top.mk
-include ../../make.mk
+include ../../build_system/make/make.mk
FATFS_PATH = lib/fatfs/source
@@ -25,14 +24,4 @@ SRC_C += \
# suppress warning caused by fatfs
CFLAGS += -Wno-error=cast-qual
-# TinyUSB Host Stack source
-SRC_C += \
- src/class/cdc/cdc_host.c \
- src/class/hid/hid_host.c \
- src/class/msc/msc_host.c \
- src/host/hub.c \
- src/host/usbh.c \
- src/portable/ohci/ohci.c \
- src/portable/nxp/lpc17_40/hcd_lpc17_40.c
-
-include ../../rules.mk
+include ../../build_system/make/rules.mk
diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt
index fa9c14857..fee10f9e2 100644
--- a/examples/host/msc_file_explorer/only.txt
+++ b/examples/host/msc_file_explorer/only.txt
@@ -1,11 +1,14 @@
+mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
-mcu:MIMXRT
+mcu:MIMXRT1XXX
mcu:MIMXRT10XX
mcu:MIMXRT11XX
mcu:RP2040
mcu:MSP432E4
mcu:RX65X
+mcu:RAXXX
+mcu:MAX3421
diff --git a/examples/host/msc_file_explorer/src/main.c b/examples/host/msc_file_explorer/src/main.c
index ab2cfd498..f6b6810f5 100644
--- a/examples/host/msc_file_explorer/src/main.c
+++ b/examples/host/msc_file_explorer/src/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -23,11 +23,43 @@
*
*/
+/* Example to show how to navigate mass storage device with built-in command line.
+ * Type help for list of supported commands and syntax (mostly linux commands)
+
+ > help
+ * help
+ Print list of commands
+ * cat
+ Usage: cat [FILE]...
+ Concatenate FILE(s) to standard output..
+ * cd
+ Usage: cd [DIR]...
+ Change the current directory to DIR.
+ * cp
+ Usage: cp SOURCE DEST
+ Copy SOURCE to DEST.
+ * ls
+ Usage: ls [DIR]...
+ List information about the FILEs (the current directory by default).
+ * pwd
+ Usage: pwd
+ Print the name of the current working directory.
+ * mkdir
+ Usage: mkdir DIR...
+ Create the DIRECTORY(ies), if they do not already exist..
+ * mv
+ Usage: mv SOURCE DEST...
+ Rename SOURCE to DEST.
+ * rm
+ Usage: rm [FILE]...
+ Remove (unlink) the FILE(s).
+ */
+
#include
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
@@ -40,18 +72,21 @@ extern bool msc_app_init(void);
extern void msc_app_task(void);
/*------------- MAIN -------------*/
-int main(void)
-{
+int main(void) {
board_init();
printf("TinyUSB Host MassStorage Explorer Example\r\n");
// init host stack on configured roothub port
tuh_init(BOARD_TUH_RHPORT);
+
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
msc_app_init();
- while (1)
- {
+ while (1) {
// tinyusb host task
tuh_task();
@@ -66,28 +101,25 @@ int main(void)
// TinyUSB Callbacks
//--------------------------------------------------------------------+
-void tuh_mount_cb(uint8_t dev_addr)
-{
+void tuh_mount_cb(uint8_t dev_addr) {
(void) dev_addr;
}
-void tuh_umount_cb(uint8_t dev_addr)
-{
+void tuh_umount_cb(uint8_t dev_addr) {
(void) dev_addr;
}
//--------------------------------------------------------------------+
// Blinking Task
//--------------------------------------------------------------------+
-void led_blinking_task(void)
-{
+void led_blinking_task(void) {
const uint32_t interval_ms = 1000;
static uint32_t start_ms = 0;
static bool led_state = false;
// Blink every interval ms
- if ( board_millis() - start_ms < interval_ms) return; // not enough time
+ if (board_millis() - start_ms < interval_ms) return; // not enough time
start_ms += interval_ms;
board_led_write(led_state);
diff --git a/examples/host/msc_file_explorer/src/msc_app.c b/examples/host/msc_file_explorer/src/msc_app.c
index 5a1635015..ddd39c674 100644
--- a/examples/host/msc_file_explorer/src/msc_app.c
+++ b/examples/host/msc_file_explorer/src/msc_app.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -25,7 +25,7 @@
#include
#include "tusb.h"
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "ff.h"
#include "diskio.h"
@@ -66,7 +66,10 @@ bool msc_app_init(void)
for(size_t i=0; icbw;
@@ -111,7 +113,7 @@ bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_da
uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun);
uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun);
- printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size));
+ printf("Disk Size: %" PRIu32 " MB\r\n", block_count / ((1024*1024)/block_size));
// printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size);
// For simplicity: we only mount 1 LUN per device
@@ -413,7 +415,7 @@ void cli_cmd_cat(EmbeddedCli *cli, char *args, void *context)
{
for(UINT c = 0; c < count; c++)
{
- const char ch = buf[c];
+ const uint8_t ch = buf[c];
if (isprint(ch) || iscntrl(ch))
{
putchar(ch);
@@ -538,10 +540,10 @@ void cli_cmd_ls(EmbeddedCli *cli, char *args, void *context)
printf("%-40s", fno.fname);
if (fno.fsize < 1024)
{
- printf("%lu B\r\n", fno.fsize);
+ printf("%" PRIu32 " B\r\n", fno.fsize);
}else
{
- printf("%lu KB\r\n", fno.fsize / 1024);
+ printf("%" PRIu32 " KB\r\n", fno.fsize / 1024);
}
}
}
diff --git a/examples/host/msc_file_explorer/src/tusb_config.h b/examples/host/msc_file_explorer/src/tusb_config.h
index ddf8368f4..c798b4383 100644
--- a/examples/host/msc_file_explorer/src/tusb_config.h
+++ b/examples/host/msc_file_explorer/src/tusb_config.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -30,28 +30,8 @@
extern "C" {
#endif
-//--------------------------------------------------------------------+
-// Board Specific Configuration
-//--------------------------------------------------------------------+
-
-#if CFG_TUSB_MCU == OPT_MCU_RP2040
-// change to 1 if using pico-pio-usb as host controller for raspberry rp2040
-#define CFG_TUH_RPI_PIO_USB 0
-#define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB
-#endif
-
-// RHPort number used for host can be defined by board.mk, default to port 0
-#ifndef BOARD_TUH_RHPORT
-#define BOARD_TUH_RHPORT 0
-#endif
-
-// RHPort max operational speed can defined by board.mk
-#ifndef BOARD_TUH_MAX_SPEED
-#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
-#endif
-
//--------------------------------------------------------------------
-// COMMON CONFIGURATION
+// Common Configuration
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
@@ -67,12 +47,6 @@
#define CFG_TUSB_DEBUG 0
#endif
-// Enable Host stack
-#define CFG_TUH_ENABLED 1
-
-// Default is max speed that hardware controller could support with on-chip PHY
-#define CFG_TUH_MAX_SPEED BOARD_TUH_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.
@@ -80,16 +54,48 @@
* - 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
+#ifndef CFG_TUH_MEM_SECTION
+#define CFG_TUH_MEM_SECTION
#endif
-#ifndef CFG_TUSB_MEM_ALIGN
-#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
+#ifndef CFG_TUH_MEM_ALIGN
+#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
-// CONFIGURATION
+// Host Configuration
+//--------------------------------------------------------------------
+
+// Enable Host stack
+#define CFG_TUH_ENABLED 1
+
+#if CFG_TUSB_MCU == OPT_MCU_RP2040
+ // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
+ // #define CFG_TUH_MAX3421 1 // use max3421 as host controller
+
+ // host roothub port is 1 if using either pio-usb or max3421
+ #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
+ #define BOARD_TUH_RHPORT 1
+ #endif
+#endif
+
+// Default is max speed that hardware controller could support with on-chip PHY
+#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
+
+//------------------------- Board Specific --------------------------
+
+// RHPort number used for host can be defined by board.mk, default to port 0
+#ifndef BOARD_TUH_RHPORT
+#define BOARD_TUH_RHPORT 0
+#endif
+
+// RHPort max operational speed can defined by board.mk
+#ifndef BOARD_TUH_MAX_SPEED
+#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
+#endif
+
+//--------------------------------------------------------------------
+// Driver Configuration
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
@@ -101,8 +107,8 @@
#define CFG_TUH_HID 0 // typical keyboard + mouse device can have 3-4 HID interfaces
#define CFG_TUH_VENDOR 0
-// max device support (excluding hub device)
-#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports
+// max device support (excluding hub device): 1 hub typically has 4 ports
+#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
//------------- MSC -------------//
#define CFG_TUH_MSC_MAXLUN 4 // typical for most card reader
diff --git a/examples/make.mk b/examples/make.mk
deleted file mode 100644
index dd7a5cf4e..000000000
--- a/examples/make.mk
+++ /dev/null
@@ -1,157 +0,0 @@
-# ---------------------------------------
-# Common make definition for all examples
-# ---------------------------------------
-
-# Build directory
-BUILD := _build/$(BOARD)
-
-PROJECT := $(notdir $(CURDIR))
-BIN := $(TOP)/_bin/$(BOARD)/$(notdir $(CURDIR))
-
-# Handy check parameter function
-check_defined = \
- $(strip $(foreach 1,$1, \
- $(call __check_defined,$1,$(strip $(value 2)))))
-__check_defined = \
- $(if $(value $1),, \
- $(error Undefined make flag: $1$(if $2, ($2))))
-
-#-------------- Select the board to build for. ------------
-
-# Board without family
-ifneq ($(wildcard $(TOP)/hw/bsp/$(BOARD)/board.mk),)
-BOARD_PATH := hw/bsp/$(BOARD)
-FAMILY :=
-endif
-
-# Board within family
-ifeq ($(BOARD_PATH),)
- BOARD_PATH := $(subst $(TOP)/,,$(wildcard $(TOP)/hw/bsp/*/boards/$(BOARD)))
- FAMILY := $(word 3, $(subst /, ,$(BOARD_PATH)))
- FAMILY_PATH = hw/bsp/$(FAMILY)
-endif
-
-ifeq ($(BOARD_PATH),)
- $(info You must provide a BOARD parameter with 'BOARD=')
- $(error Invalid BOARD specified)
-endif
-
-ifeq ($(FAMILY),)
- include $(TOP)/hw/bsp/$(BOARD)/board.mk
-else
- # Include Family and Board specific defs
- include $(TOP)/$(FAMILY_PATH)/family.mk
-
- SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FAMILY_PATH)/*.c))
-endif
-
-
-#-------------- Cross Compiler ------------
-# Can be set by board, default to ARM GCC
-CROSS_COMPILE ?= arm-none-eabi-
-
-# Allow for -Os to be changed by board makefiles in case -Os is not allowed
-CFLAGS_OPTIMIZED ?= -Os
-
-ifeq ($(CC),iccarm)
-USE_IAR = 1
-endif
-
-ifdef USE_IAR
- AS = iasmarm
- LD = ilinkarm
- OBJCOPY = ielftool
- SIZE = echo "size not available for IAR"
-
-else
- CC = $(CROSS_COMPILE)gcc
- CXX = $(CROSS_COMPILE)g++
- AS = $(CC) -x assembler-with-cpp
- LD = $(CC)
-
- GDB = $(CROSS_COMPILE)gdb
- OBJCOPY = $(CROSS_COMPILE)objcopy
- SIZE = $(CROSS_COMPILE)size
-endif
-
-MKDIR = mkdir
-
-ifeq ($(CMDEXE),1)
- CP = copy
- RM = del
- PYTHON = python
-else
- SED = sed
- CP = cp
- RM = rm
- PYTHON = python3
-endif
-
-#-------------- Source files and compiler flags --------------
-
-# Include all source C in family & board folder
-SRC_C += hw/bsp/board.c
-SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(BOARD_PATH)/*.c))
-
-INC += $(TOP)/$(FAMILY_PATH)
-
-# GCC Compiler Flags
-GCC_CFLAGS += \
- -ggdb \
- -fdata-sections \
- -ffunction-sections \
- -fsingle-precision-constant \
- -fno-strict-aliasing \
- -Wall \
- -Wextra \
- -Werror \
- -Wfatal-errors \
- -Wdouble-promotion \
- -Wstrict-prototypes \
- -Wstrict-overflow \
- -Werror-implicit-function-declaration \
- -Wfloat-equal \
- -Wundef \
- -Wshadow \
- -Wwrite-strings \
- -Wsign-compare \
- -Wmissing-format-attribute \
- -Wunreachable-code \
- -Wcast-align \
- -Wcast-function-type \
- -Wcast-qual \
- -Wnull-dereference \
- -Wuninitialized \
- -Wunused \
- -Wredundant-decls
-
-# conversion is too strict for most mcu driver, may be disable sign/int/arith-conversion
-# -Wconversion
-
-# Debugging/Optimization
-ifeq ($(DEBUG), 1)
- GCC_CFLAGS += -O0
- NO_LTO = 1
-else
- GCC_CFLAGS += $(CFLAGS_OPTIMIZED)
-endif
-
-# Log level is mapped to TUSB DEBUG option
-ifneq ($(LOG),)
- CMAKE_DEFSYM += -DLOG=$(LOG)
- CFLAGS += -DCFG_TUSB_DEBUG=$(LOG)
-endif
-
-# Logger: default is uart, can be set to rtt or swo
-ifneq ($(LOGGER),)
- CMAKE_DEFSYM += -DLOGGER=$(LOGGER)
-endif
-
-ifeq ($(LOGGER),rtt)
- CFLAGS += -DLOGGER_RTT -DSEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL
- RTT_SRC = lib/SEGGER_RTT
- INC += $(TOP)/$(RTT_SRC)/RTT
- SRC_C += $(RTT_SRC)/RTT/SEGGER_RTT.c
-else ifeq ($(LOGGER),swo)
- CFLAGS += -DLOGGER_SWO
-endif
diff --git a/examples/typec/CMakeLists.txt b/examples/typec/CMakeLists.txt
new file mode 100644
index 000000000..c7641494e
--- /dev/null
+++ b/examples/typec/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 3.17)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake)
+
+project(tinyusb_host_examples C CXX ASM)
+family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR})
+
+# family_add_subdirectory will filter what to actually add based on selected FAMILY
+family_add_subdirectory(power_delivery)
diff --git a/examples/typec/power_delivery/CMakeLists.txt b/examples/typec/power_delivery/CMakeLists.txt
new file mode 100644
index 000000000..012eff095
--- /dev/null
+++ b/examples/typec/power_delivery/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.17)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
+
+# gets PROJECT name for the example (e.g. -)
+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/main.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/typec/power_delivery/Makefile b/examples/typec/power_delivery/Makefile
new file mode 100644
index 000000000..7fa475da5
--- /dev/null
+++ b/examples/typec/power_delivery/Makefile
@@ -0,0 +1,11 @@
+include ../../build_system/make/make.mk
+
+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/typec/power_delivery/only.txt b/examples/typec/power_delivery/only.txt
new file mode 100644
index 000000000..657aeaac5
--- /dev/null
+++ b/examples/typec/power_delivery/only.txt
@@ -0,0 +1 @@
+mcu:STM32G4
diff --git a/examples/typec/power_delivery/src/main.c b/examples/typec/power_delivery/src/main.c
new file mode 100644
index 000000000..489d01aa1
--- /dev/null
+++ b/examples/typec/power_delivery/src/main.c
@@ -0,0 +1,193 @@
+/*
+ * 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
+#include
+
+#include "bsp/board_api.h"
+#include "tusb.h"
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF PROTOTYPES
+//--------------------------------------------------------------------+
+
+// Voltage and current for selecting PDO
+// DANGEROUS: Please make sure your board can withstand the voltage and current
+// defined here. Otherwise, you may damage your board, smoke can come out
+#define VOLTAGE_MAX_MV 5000 // maximum voltage in mV
+#define CURRENT_MAX_MA 500 // maximum current in mA
+#define CURRENT_OPERATING_MA 100 // operating current in mA
+
+/* Blink pattern
+ * - 250 ms : button is not pressed
+ * - 1000 ms : button is pressed (and hold)
+ */
+enum {
+ BLINK_PRESSED = 250,
+ BLINK_UNPRESSED = 1000
+};
+
+static uint32_t blink_interval_ms = BLINK_UNPRESSED;
+
+void led_blinking_task(void);
+
+#define HELLO_STR "Hello from TinyUSB\r\n"
+
+int main(void)
+{
+ board_init();
+ board_led_write(true);
+
+ tuc_init(0, TUSB_TYPEC_PORT_SNK);
+
+ while (1) {
+ led_blinking_task();
+
+ // tinyusb typec task
+ tuc_task();
+ }
+}
+
+#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3
+void app_main(void)
+{
+ main();
+}
+#endif
+
+//--------------------------------------------------------------------+
+// TypeC PD callbacks
+//--------------------------------------------------------------------+
+
+bool tuc_pd_data_received_cb(uint8_t rhport, pd_header_t const* header, uint8_t const* dobj, uint8_t const* p_end) {
+ switch (header->msg_type) {
+ case PD_DATA_SOURCE_CAP: {
+ printf("PD Source Capabilities\r\n");
+ // Examine source capability and select a suitable PDO (starting from 1 with safe5v)
+ uint8_t selected_pos = 1;
+
+ for(size_t i=0; in_data_obj; i++) {
+ TU_VERIFY(dobj < p_end);
+ uint32_t const pdo = tu_le32toh(tu_unaligned_read32(dobj));
+
+ switch ((pdo >> 30) & 0x03ul) {
+ case PD_PDO_TYPE_FIXED: {
+ pd_pdo_fixed_t const* fixed = (pd_pdo_fixed_t const*) &pdo;
+ uint32_t const voltage_mv = fixed->voltage_50mv*50;
+ uint32_t const current_ma = fixed->current_max_10ma*10;
+ printf("[Fixed] %lu mV %lu mA\r\n", voltage_mv, current_ma);
+
+ if (voltage_mv <= VOLTAGE_MAX_MV && current_ma >= CURRENT_MAX_MA) {
+ // Found a suitable PDO
+ selected_pos = i+1;
+ }
+
+ break;
+ }
+
+ case PD_PDO_TYPE_BATTERY:
+ break;
+
+ case PD_PDO_TYPE_VARIABLE:
+ break;
+
+ case PD_PDO_TYPE_APDO:
+ break;
+ }
+
+ dobj += 4;
+ }
+
+ //------------- Response with selected PDO -------------//
+ // Be careful and make sure your board can withstand the selected PDO
+ // voltage other than safe5v e.g 12v or 20v
+
+ printf("Selected PDO %u\r\n", selected_pos);
+
+ // Send request with selected PDO position as response to Source Cap
+ pd_rdo_fixed_variable_t rdo = {
+ .current_extremum_10ma = 50, // max 500mA
+ .current_operate_10ma = 30, // 300mA
+ .reserved = 0,
+ .epr_mode_capable = 0,
+ .unchunked_ext_msg_support = 0,
+ .no_usb_suspend = 0,
+ .usb_comm_capable = 1,
+ .capability_mismatch = 0,
+ .give_back_flag = 0, // exteremum is max
+ .object_position = selected_pos,
+ };
+ tuc_msg_request(rhport, &rdo);
+
+ break;
+ }
+
+ default: break;
+ }
+
+ return true;
+}
+
+bool tuc_pd_control_received_cb(uint8_t rhport, pd_header_t const* header) {
+ (void) rhport;
+ switch (header->msg_type) {
+ case PD_CTRL_ACCEPT:
+ printf("PD Request Accepted\r\n");
+ // preparing for power transition
+ break;
+
+ case PD_CTRL_REJECT:
+ printf("PD Request Rejected\r\n");
+ // try to negotiate further power
+ break;
+
+ case PD_CTRL_PS_READY:
+ printf("PD Power Ready\r\n");
+ // Source is ready to supply power
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+//--------------------------------------------------------------------+
+// 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/typec/power_delivery/src/tusb_config.h b/examples/typec/power_delivery/src/tusb_config.h
new file mode 100644
index 000000000..f7cb3cc04
--- /dev/null
+++ b/examples/typec/power_delivery/src/tusb_config.h
@@ -0,0 +1,83 @@
+/*
+ * 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
+
+//--------------------------------------------------------------------
+// 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
+
+#define CFG_TUD_ENABLED 0
+#define CFG_TUH_ENABLED 0
+
+// Enable TYPEC stack
+#define CFG_TUC_ENABLED 1
+
+
+// special example that doesn't enable device or host stack
+// This can cause some TinyUSB API missing, this define hack to allow us to fill those API
+// to pass the compilation process
+#if CFG_TUD_ENABLED == 0
+#define tud_int_handler(x)
+#endif
+
+
+// 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
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_CONFIG_H_ */
diff --git a/hw/bsp/ansi_escape.h b/hw/bsp/ansi_escape.h
index 6e62ee20a..15af2f3ab 100644
--- a/hw/bsp/ansi_escape.h
+++ b/hw/bsp/ansi_escape.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
diff --git a/hw/bsp/board.c b/hw/bsp/board.c
index 14858c2b6..bb339f613 100644
--- a/hw/bsp/board.c
+++ b/hw/bsp/board.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2018, hathach (tinyusb.org)
@@ -23,56 +23,7 @@
*
*/
-#include "board.h"
-
-#if 0
-#define LED_PHASE_MAX 8
-
-static struct
-{
- uint32_t phase[LED_PHASE_MAX];
- uint8_t phase_count;
-
- bool led_state;
- uint8_t current_phase;
- uint32_t current_ms;
-}led_pattern;
-
-void board_led_pattern(uint32_t const phase_ms[], uint8_t count)
-{
- memcpy(led_pattern.phase, phase_ms, 4*count);
- led_pattern.phase_count = count;
-
- // reset with 1st phase is on
- led_pattern.current_ms = board_millis();
- led_pattern.current_phase = 0;
- led_pattern.led_state = true;
- board_led_on();
-}
-
-void board_led_task(void)
-{
- if ( led_pattern.phase_count == 0 ) return;
-
- uint32_t const duration = led_pattern.phase[led_pattern.current_phase];
-
- // return if not enough time
- if (board_millis() - led_pattern.current_ms < duration) return;
-
- led_pattern.led_state = !led_pattern.led_state;
- board_led_write(led_pattern.led_state);
-
- led_pattern.current_ms += duration;
- led_pattern.current_phase++;
-
- if (led_pattern.current_phase == led_pattern.phase_count)
- {
- led_pattern.current_phase = 0;
- led_pattern.led_state = true;
- board_led_on();
- }
-}
-#endif
+#include "board_api.h"
//--------------------------------------------------------------------+
// newlib read()/write() retarget
@@ -95,15 +46,13 @@ void board_led_task(void)
#if !(defined __SES_ARM) && !(defined __SES_RISCV) && !(defined __CROSSWORKS_ARM)
#include "SEGGER_RTT.h"
-TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count)
-{
+TU_ATTR_USED int sys_write(int fhdl, const char *buf, size_t count) {
(void) fhdl;
- SEGGER_RTT_Write(0, (const char*) buf, (int) count);
- return count;
+ SEGGER_RTT_Write(0, (const char *) buf, (int) count);
+ return (int) count;
}
-TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count)
-{
+TU_ATTR_USED int sys_read(int fhdl, char *buf, size_t count) {
(void) fhdl;
int rd = (int) SEGGER_RTT_Read(0, buf, count);
return (rd > 0) ? rd : -1;
@@ -113,22 +62,20 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count)
#elif defined(LOGGER_SWO)
// Logging with SWO for ARM Cortex
-
#include "board_mcu.h"
-TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count)
-{
+TU_ATTR_USED int sys_write (int fhdl, const char *buf, size_t count) {
(void) fhdl;
uint8_t const* buf8 = (uint8_t const*) buf;
- for(size_t i=0; i 0) ? rd : -1;
@@ -153,8 +98,39 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count)
#endif
-int board_getchar(void)
-{
- char c;
- return ( sys_read(0, &c, 1) > 0 ) ? (int) c : (-1);
+//TU_ATTR_USED int _close(int fhdl) {
+// (void) fhdl;
+// return 0;
+//}
+
+//TU_ATTR_USED int _fstat(int file, struct stat *st) {
+// memset(st, 0, sizeof(*st));
+// st->st_mode = S_IFCHR;
+//}
+
+// Clang use picolibc
+#if defined(__clang__)
+static int cl_putc(char c, FILE *f) {
+ (void) f;
+ return sys_write(0, &c, 1);
+}
+
+static int cl_getc(FILE* f) {
+ (void) f;
+ char c;
+ return sys_read(0, &c, 1) > 0 ? c : -1;
+}
+
+static FILE __stdio = FDEV_SETUP_STREAM(cl_putc, cl_getc, NULL, _FDEV_SETUP_RW);
+FILE *const stdin = &__stdio;
+__strong_reference(stdin, stdout);
+__strong_reference(stdin, stderr);
+#endif
+
+//--------------------------------------------------------------------+
+// Board API
+//--------------------------------------------------------------------+
+int board_getchar(void) {
+ char c;
+ return (sys_read(0, &c, 1) > 0) ? (int) c : (-1);
}
diff --git a/hw/bsp/board.h b/hw/bsp/board.h
deleted file mode 100644
index 0a10294d0..000000000
--- a/hw/bsp/board.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * 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.
- *
- * This file is part of the TinyUSB stack.
- */
-
-/** \ingroup group_demo
- * \defgroup group_board Boards Abstraction Layer
- * @{ */
-
-#ifndef _BSP_BOARD_H_
-#define _BSP_BOARD_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#include
-#include
-
-#include "ansi_escape.h"
-#include "tusb.h"
-
-// Define the default baudrate
-#ifndef CFG_BOARD_UART_BAUDRATE
-#define CFG_BOARD_UART_BAUDRATE 115200 ///< Default baud rate
-#endif
-
-//--------------------------------------------------------------------+
-// Board Porting API
-// For simplicity, only one LED and one Button are used
-//--------------------------------------------------------------------+
-
-// Initialize on-board peripherals : led, button, uart and USB
-void board_init(void);
-
-// Turn LED on or off
-void board_led_write(bool state);
-
-// Control led pattern using phase duration in ms.
-// For each phase, LED is toggle then repeated, board_led_task() is required to be called
-//void board_led_pattern(uint32_t const phase_ms[], uint8_t count);
-
-// Get the current state of button
-// a '1' means active (pressed), a '0' means inactive.
-uint32_t board_button_read(void);
-
-// Get characters from UART
-// Return number of read bytes
-int board_uart_read(uint8_t* buf, int len);
-
-// Send characters to UART
-// Return number of sent bytes
-int board_uart_write(void const * buf, int len);
-
-#if CFG_TUSB_OS == OPT_OS_NONE
- // Get current milliseconds, must be implemented when no RTOS is used
- uint32_t board_millis(void);
-
-#elif CFG_TUSB_OS == OPT_OS_FREERTOS
- static inline uint32_t board_millis(void)
- {
- return ( ( ((uint64_t) xTaskGetTickCount()) * 1000) / configTICK_RATE_HZ );
- }
-
-#elif CFG_TUSB_OS == OPT_OS_MYNEWT
- static inline uint32_t board_millis(void)
- {
- return os_time_ticks_to_ms32( os_time_get() );
- }
-
-#elif CFG_TUSB_OS == OPT_OS_PICO
- #include "pico/time.h"
- static inline uint32_t board_millis(void)
- {
- return to_ms_since_boot(get_absolute_time());
- }
-
-#elif CFG_TUSB_OS == OPT_OS_RTTHREAD
- static inline uint32_t board_millis(void)
- {
- return (((uint64_t)rt_tick_get()) * 1000 / RT_TICK_PER_SECOND);
- }
-
-#else
- #error "board_millis() is not implemented for this OS"
-#endif
-
-//--------------------------------------------------------------------+
-// Helper functions
-//--------------------------------------------------------------------+
-static inline void board_led_on(void)
-{
- board_led_write(true);
-}
-
-static inline void board_led_off(void)
-{
- board_led_write(false);
-}
-
-// TODO remove
-static inline void board_delay(uint32_t ms)
-{
- uint32_t start_ms = board_millis();
- while (board_millis() - start_ms < ms)
- {
- #if CFG_TUD_ENABLED
- // take chance to run usb background
- tud_task();
- #endif
- }
-}
-
-// stdio getchar() is blocking, this is non-blocking version
-int board_getchar(void);
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* _BSP_BOARD_H_ */
-
-/** @} */
diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h
new file mode 100644
index 000000000..eee9ed9c5
--- /dev/null
+++ b/hw/bsp/board_api.h
@@ -0,0 +1,194 @@
+/*
+ * 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.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef _BOARD_API_H_
+#define _BOARD_API_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#include
+
+#include "tusb.h"
+
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+#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"
+#else
+ #include "FreeRTOS.h"
+ #include "semphr.h"
+ #include "queue.h"
+ #include "task.h"
+ #include "timers.h"
+#endif
+#endif
+
+// Define the default baudrate
+#ifndef CFG_BOARD_UART_BAUDRATE
+#define CFG_BOARD_UART_BAUDRATE 115200 ///< Default baud rate
+#endif
+
+//--------------------------------------------------------------------+
+// Board Porting API
+// For simplicity, only one LED and one Button are used
+//--------------------------------------------------------------------+
+
+// Initialize on-board peripherals : led, button, uart and USB
+void board_init(void);
+
+// Init board after tinyusb is initialized
+void board_init_after_tusb(void) TU_ATTR_WEAK;
+
+// Turn LED on or off
+void board_led_write(bool state);
+
+// Control led pattern using phase duration in ms.
+// For each phase, LED is toggle then repeated, board_led_task() is required to be called
+//void board_led_pattern(uint32_t const phase_ms[], uint8_t count);
+
+// Get the current state of button
+// a '1' means active (pressed), a '0' means inactive.
+uint32_t board_button_read(void);
+
+// Get board unique ID for USB serial number. Return number of bytes. Note max_len is typically 16
+TU_ATTR_WEAK size_t board_get_unique_id(uint8_t id[], size_t max_len);
+
+// Get characters from UART. Return number of read bytes
+int board_uart_read(uint8_t *buf, int len);
+
+// Send characters to UART. Return number of sent bytes
+int board_uart_write(void const *buf, int len);
+
+#if CFG_TUSB_OS == OPT_OS_NONE
+// Get current milliseconds, must be implemented when no RTOS is used
+uint32_t board_millis(void);
+
+#elif CFG_TUSB_OS == OPT_OS_FREERTOS
+static inline uint32_t board_millis(void) {
+ return ( ( ((uint64_t) xTaskGetTickCount()) * 1000) / configTICK_RATE_HZ );
+}
+
+#elif CFG_TUSB_OS == OPT_OS_MYNEWT
+static inline uint32_t board_millis(void) {
+ return os_time_ticks_to_ms32( os_time_get() );
+}
+
+#elif CFG_TUSB_OS == OPT_OS_PICO
+#include "pico/time.h"
+static inline uint32_t board_millis(void) {
+ return to_ms_since_boot(get_absolute_time());
+}
+
+#elif CFG_TUSB_OS == OPT_OS_RTTHREAD
+static inline uint32_t board_millis(void) {
+ return (((uint64_t)rt_tick_get()) * 1000 / RT_TICK_PER_SECOND);
+}
+
+#elif CFG_TUSB_OS == OPT_OS_CUSTOM
+// Implement your own board_millis() in any of .c file
+uint32_t board_millis(void);
+
+#else
+ #error "board_millis() is not implemented for this OS"
+#endif
+
+//--------------------------------------------------------------------+
+// Helper functions
+//--------------------------------------------------------------------+
+static inline void board_led_on(void) {
+ board_led_write(true);
+}
+
+static inline void board_led_off(void) {
+ board_led_write(false);
+}
+
+// Get USB Serial number string from unique ID if available. Return number of character.
+// Input is string descriptor from index 1 (index 0 is type + len)
+static inline size_t board_usb_get_serial(uint16_t desc_str1[], size_t max_chars) {
+ uint8_t uid[16] TU_ATTR_ALIGNED(4);
+ size_t uid_len;
+
+ // TODO work with make, but not working with esp32s3 cmake
+ if ( board_get_unique_id ) {
+ uid_len = board_get_unique_id(uid, sizeof(uid));
+ }else {
+ // fixed serial string is 01234567889ABCDEF
+ uint32_t* uid32 = (uint32_t*) (uintptr_t) uid;
+ uid32[0] = 0x67452301;
+ uid32[1] = 0xEFCDAB89;
+ uid_len = 8;
+ }
+
+ if ( uid_len > max_chars / 2 ) uid_len = max_chars / 2;
+
+ for ( size_t i = 0; i < uid_len; i++ ) {
+ for ( size_t j = 0; j < 2; j++ ) {
+ const char nibble_to_hex[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+ uint8_t const nibble = (uid[i] >> (j * 4)) & 0xf;
+ desc_str1[i * 2 + (1 - j)] = nibble_to_hex[nibble]; // UTF-16-LE
+ }
+ }
+
+ return 2 * uid_len;
+}
+
+// TODO remove
+static inline void board_delay(uint32_t ms) {
+ uint32_t start_ms = board_millis();
+ while ( board_millis() - start_ms < ms ) {
+ // take chance to run usb background
+ #if CFG_TUD_ENABLED
+ tud_task();
+ #endif
+
+ #if CFG_TUH_ENABLED
+ tuh_task();
+ #endif
+ }
+}
+
+// stdio getchar() is blocking, this is non-blocking version
+int board_getchar(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h
index 18f071a22..013eb1c83 100644
--- a/hw/bsp/board_mcu.h
+++ b/hw/bsp/board_mcu.h
@@ -39,23 +39,23 @@
//--------------------------------------------------------------------+
// Include order follows OPT_MCU_ number
-#if CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13XX || \
- CFG_TUSB_MCU == OPT_MCU_LPC15XX || CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \
- CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC18XX || \
- CFG_TUSB_MCU == OPT_MCU_LPC40XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX
+#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX) || \
+ TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC18XX) || \
+ TU_CHECK_MCU(OPT_MCU_LPC40XX, OPT_MCU_LPC43XX)
#include "chip.h"
-#elif CFG_TUSB_MCU == OPT_MCU_LPC51UXX || CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \
- CFG_TUSB_MCU == OPT_MCU_LPC55XX || CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || \
- CFG_TUSB_MCU == OPT_MCU_K32L2BXX
+#elif TU_CHECK_MCU(OPT_MCU_LPC51UXX, OPT_MCU_LPC54XXX, OPT_MCU_LPC55XX, OPT_MCU_MCXN9)
+ #include "fsl_device_registers.h"
+
+#elif TU_CHECK_MCU(OPT_MCU_KINETIS_KL, OPT_MCU_KINETIS_K32L, OPT_MCU_KINETIS_K)
#include "fsl_device_registers.h"
#elif CFG_TUSB_MCU == OPT_MCU_NRF5X
#include "nrf.h"
#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \
- CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \
- CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21
+ CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \
+ CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21
#include "sam.h"
#elif CFG_TUSB_MCU == OPT_MCU_SAMG
@@ -83,6 +83,9 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32G4
#include "stm32g4xx.h"
+#elif CFG_TUSB_MCU == OPT_MCU_STM32H5
+ #include "stm32h5xx.h"
+
#elif CFG_TUSB_MCU == OPT_MCU_STM32H7
#include "stm32h7xx.h"
@@ -101,6 +104,9 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32U5
#include "stm32u5xx.h"
+#elif CFG_TUSB_MCU == OPT_MCU_STM32G0
+ #include "stm32g0xx.h"
+
#elif CFG_TUSB_MCU == OPT_MCU_CXD56
// no header needed
@@ -113,7 +119,7 @@
#elif CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI
// no header needed
-#elif CFG_TUSB_MCU == OPT_MCU_MIMXRT
+#elif CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX
#include "fsl_device_registers.h"
#elif CFG_TUSB_MCU == OPT_MCU_NUC120
@@ -136,13 +142,16 @@
#elif CFG_TUSB_MCU == OPT_MCU_RP2040
#include "pico.h"
-
+
#elif CFG_TUSB_MCU == OPT_MCU_EFM32GG
#include "em_device.h"
#elif CFG_TUSB_MCU == OPT_MCU_RX63X || CFG_TUSB_MCU == OPT_MCU_RX65X
// no header needed
+#elif CFG_TUSB_MCU == OPT_MCU_RAXXX
+ #include "bsp_api.h"
+
#elif CFG_TUSB_MCU == OPT_MCU_GD32VF103
#include "gd32vf103.h"
@@ -155,6 +164,9 @@
#elif CFG_TUSB_MCU == OPT_MCU_TM4C123
#include "TM4C123.h"
+#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X
+ #include "ch32f20x.h"
+
#elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837)
// no header needed
diff --git a/hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.h b/hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.h
index 1d3565d5c..84a106346 100644
--- a/hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.h
+++ b/hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
diff --git a/hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.mk b/hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.mk
index 52e9e45c4..052033230 100644
--- a/hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.mk
+++ b/hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.mk
@@ -1,5 +1,5 @@
-CFLAGS += -mcpu=arm1176jzf-s \
- -DBCM_VERSION=2835 \
+CPU_CORE = arm1176
+CFLAGS += -DBCM_VERSION=2835 \
-DCFG_TUSB_MCU=OPT_MCU_BCM2835
-SUFFIX =
+SUFFIX =
diff --git a/hw/bsp/broadcom_32bit/family.c b/hw/bsp/broadcom_32bit/family.c
index f7a11fb49..664b4dcaf 100644
--- a/hw/bsp/broadcom_32bit/family.c
+++ b/hw/bsp/broadcom_32bit/family.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -24,7 +24,7 @@
* This file is part of the TinyUSB stack.
*/
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "board.h"
#include "broadcom/cpu.h"
diff --git a/hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.h b/hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.h
index 1d3565d5c..84a106346 100644
--- a/hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.h
+++ b/hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
diff --git a/hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.mk b/hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.mk
index 5706b8318..702f10137 100644
--- a/hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.mk
+++ b/hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.mk
@@ -1,3 +1,3 @@
-CFLAGS += -mcpu=cortex-a72 \
- -DBCM_VERSION=2711 \
+CPU_CORE = cortex-a72
+CFLAGS += -DBCM_VERSION=2711 \
-DCFG_TUSB_MCU=OPT_MCU_BCM2711
diff --git a/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.h b/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.h
index 1d3565d5c..84a106346 100644
--- a/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.h
+++ b/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
diff --git a/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.mk b/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.mk
index 3060b0571..da3fe17bc 100644
--- a/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.mk
+++ b/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.mk
@@ -1,3 +1,3 @@
-CFLAGS += -mcpu=cortex-a53 \
- -DBCM_VERSION=2837 \
+CPU_CORE = cortex-a53
+CFLAGS += -DBCM_VERSION=2837 \
-DCFG_TUSB_MCU=OPT_MCU_BCM2837
diff --git a/hw/bsp/broadcom_64bit/family.c b/hw/bsp/broadcom_64bit/family.c
index f7a11fb49..664b4dcaf 100644
--- a/hw/bsp/broadcom_64bit/family.c
+++ b/hw/bsp/broadcom_64bit/family.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -24,7 +24,7 @@
* This file is part of the TinyUSB stack.
*/
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "board.h"
#include "broadcom/cpu.h"
diff --git a/hw/bsp/brtmm90x/family.c b/hw/bsp/brtmm90x/family.c
index 3b6b03904..4d81e7d52 100644
--- a/hw/bsp/brtmm90x/family.c
+++ b/hw/bsp/brtmm90x/family.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright 2021 Bridgetek Pte Ltd
@@ -24,7 +24,7 @@
* This file is part of the TinyUSB stack.
*/
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "board.h"
#include
@@ -70,7 +70,7 @@ void board_init(void)
board_uart_write(WELCOME_MSG, sizeof(WELCOME_MSG));
#ifdef BOARD_GPIO_LED
- gpio_function(BOARD_GPIO_LED, pad_func_0);
+ gpio_function(BOARD_GPIO_LED, pad_func_0);
gpio_idrive(BOARD_GPIO_LED, pad_drive_12mA);
gpio_dir(BOARD_GPIO_LED, pad_dir_output);
#endif
@@ -233,7 +233,7 @@ int board_uart_write(void const *buf, int len)
uint32_t board_millis(void)
{
uint32_t safe_ms;
-
+
CRITICAL_SECTION_BEGIN
safe_ms = timer_ms;
CRITICAL_SECTION_END
@@ -254,4 +254,3 @@ void chip_reboot(void)
dbg_memory_copy(0xfe, 0, 0, 255);
#endif
}
-
diff --git a/hw/bsp/brtmm90x/family.mk b/hw/bsp/brtmm90x/family.mk
index 0ddf47a3a..6df0bfdfe 100644
--- a/hw/bsp/brtmm90x/family.mk
+++ b/hw/bsp/brtmm90x/family.mk
@@ -5,7 +5,7 @@ SKIP_NANOLIB = 1
# Set to use FT90X prebuilt libraries.
FT9XX_PREBUILT_LIBS = 0
ifeq ($(FT9XX_PREBUILT_LIBS),1)
-# If the FT90X toolchain is installed on Windows systems then the SDK
+# If the FT90X toolchain is installed on Windows systems then the SDK
# include files and prebuilt libraries are at: %FT90X_TOOLCHAIN%/hardware
FT9XX_SDK = $(FT90X_TOOLCHAIN)/hardware
INC += "$(FT9XX_SDK)/include"
@@ -21,7 +21,7 @@ endif
# Add include files which are within the TinyUSB directory structure.
INC += \
- $(TOP)/$(BOARD_PATH)
+ $(TOP)/$(BOARD_PATH)
# Add required C Compiler flags for FT90X.
CFLAGS += \
@@ -30,7 +30,7 @@ CFLAGS += \
-fvar-tracking-assignments \
-fmessage-length=0 \
-ffunction-sections \
- -DCFG_TUSB_MCU=OPT_MCU_FT90X
+ -DCFG_TUSB_MCU=OPT_MCU_FT90X
# Maximum USB device speed supported by the board
CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED
@@ -45,7 +45,7 @@ LDFLAGS += $(addprefix -L,$(LDINC)) \
-Wl,-lc
# Additional Source files for FT90X.
-SRC_C += src/portable/bridgetek/ft9xx/dcd_ft9xx.c
+SRC_C += src/portable/bridgetek/ft9xx/dcd_ft9xx.c
# Linker library.
ifneq ($(FT9XX_PREBUILT_LIBS),1)
diff --git a/hw/bsp/ch32f20x/boards/ch32f205r-r0/board.h b/hw/bsp/ch32f20x/boards/ch32f205r-r0/board.h
new file mode 100644
index 000000000..d5849bddb
--- /dev/null
+++ b/hw/bsp/ch32f20x/boards/ch32f205r-r0/board.h
@@ -0,0 +1,59 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023, Denis Krasutski
+ *
+ * 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 BOARD_H_
+#define BOARD_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// LED: need to wire pin LED1 to PC0 in the P1 header
+#define LED_PORT GPIOC
+#define LED_PIN GPIO_Pin_1
+#define LED_STATE_ON 0
+#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE)
+
+// Button: need to wire pin KEY to PC1 in the P1 header
+#define BUTTON_PORT GPIOC
+#define BUTTON_PIN GPIO_Pin_0
+#define BUTTON_STATE_ACTIVE 0
+#define BUTTON_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE)
+
+// UART
+#define UART_DEV USART2
+#define UART_DEV_IRQn USART2_IRQn
+#define UART_DEV_IRQHandler USART2_IRQHandler
+#define UART_DEV_GPIO_PORT GPIOA
+#define UART_DEV_TX_PIN GPIO_Pin_2
+#define UART_DEV_CLK_EN() do { \
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); \
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); \
+ } while(0)
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/hw/bsp/ch32f20x/boards/ch32f205r-r0/board.mk b/hw/bsp/ch32f20x/boards/ch32f205r-r0/board.mk
new file mode 100644
index 000000000..f0e9bf30f
--- /dev/null
+++ b/hw/bsp/ch32f20x/boards/ch32f205r-r0/board.mk
@@ -0,0 +1,7 @@
+LD_FILE = $(FAMILY_PATH)/ch32f205.ld
+
+SRC_S += \
+ $(FAMILY_PATH)/startup_gcc_ch32f20x_d8c.s
+
+CFLAGS += \
+ -DCH32F20x_D8C
diff --git a/hw/bsp/ch32f20x/ch32f205.ld b/hw/bsp/ch32f20x/ch32f205.ld
new file mode 100644
index 000000000..7c8d04cc5
--- /dev/null
+++ b/hw/bsp/ch32f20x/ch32f205.ld
@@ -0,0 +1,111 @@
+ENTRY(Reset_Handler)
+
+_Min_Heap_Size = 0x200;
+_Min_Stack_Size = 0x400;
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
+}
+SECTIONS
+{
+ .isr_vector :
+ {
+ . = ALIGN(4);
+ KEEP(*(.isr_vector))
+ . = ALIGN(4);
+ } >FLASH
+
+ .text :
+ {
+ . = ALIGN(4);
+ _stext = .;
+ *(.text)
+ *(.text*)
+ *(.glue_7)
+ *(.glue_7t)
+ *(.eh_frame)
+ KEEP (*(.init))
+ KEEP (*(.fini))
+ . = ALIGN(4);
+ _etext = .;
+ } >FLASH
+ .rodata :
+ {
+ . = ALIGN(4);
+ *(.rodata)
+ *(.rodata*)
+ . = ALIGN(4);
+ } >FLASH
+ .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
+ .ARM : {
+ __exidx_start = .;
+ *(.ARM.exidx*)
+ __exidx_end = .;
+ } >FLASH
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array*))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ } >FLASH
+ .init_array :
+ {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array*))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ } >FLASH
+ .fini_array :
+ {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(SORT(.fini_array.*)))
+ KEEP (*(.fini_array*))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ } >FLASH
+ _sidata = LOADADDR(.data);
+ .data :
+ {
+ . = ALIGN(4);
+ _sdata = .;
+ *(.data)
+ *(.data*)
+ . = ALIGN(4);
+ _edata = .;
+ } >RAM AT> FLASH
+ . = ALIGN(4);
+ .bss :
+ {
+ _sbss = .;
+ __bss_start__ = _sbss;
+ *(.bss)
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ __bss_end__ = _ebss;
+ } >RAM
+ ._user_heap_stack :
+ {
+ . = ALIGN(4);
+ PROVIDE ( end = . );
+ PROVIDE ( _end = . );
+ __HeapStart = .;
+ . = . + _Min_Heap_Size;
+ __HeapEnd = .;
+ __StackLimit = .;
+ . = . + _Min_Stack_Size;
+ __StackTop = .;
+ . = ALIGN(4);
+ } >RAM
+_estack = __StackTop;
+_sstack = __StackLimit;
+ /DISCARD/ :
+ {
+ libc.a ( * )
+ libm.a ( * )
+ libgcc.a ( * )
+ }
+ .ARM.attributes 0 : { *(.ARM.attributes) }
+}
diff --git a/hw/bsp/ch32f20x/ch32f20x_conf.h b/hw/bsp/ch32f20x/ch32f20x_conf.h
new file mode 100644
index 000000000..05199ff95
--- /dev/null
+++ b/hw/bsp/ch32f20x/ch32f20x_conf.h
@@ -0,0 +1,39 @@
+/********************************** (C) COPYRIGHT *******************************
+ * File Name : ch32f20x_conf.h
+ * Author : WCH
+ * Version : V1.0.0
+ * Date : 2021/08/08
+ * Description : Library configuration file.
+ *********************************************************************************
+ * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
+ * Attention: This software (modified or not) and binary are used for
+ * microcontroller manufactured by Nanjing Qinheng Microelectronics.
+ *******************************************************************************/
+#ifndef __CH32F20x_CONF_H
+#define __CH32F20x_CONF_H
+
+#include "ch32f20x_adc.h"
+#include "ch32f20x_bkp.h"
+#include "ch32f20x_can.h"
+#include "ch32f20x_crc.h"
+#include "ch32f20x_dac.h"
+#include "ch32f20x_dbgmcu.h"
+#include "ch32f20x_dma.h"
+#include "ch32f20x_exti.h"
+#include "ch32f20x_flash.h"
+#include "ch32f20x_fsmc.h"
+#include "ch32f20x_gpio.h"
+#include "ch32f20x_i2c.h"
+#include "ch32f20x_iwdg.h"
+#include "ch32f20x_pwr.h"
+#include "ch32f20x_rcc.h"
+#include "ch32f20x_rtc.h"
+#include "ch32f20x_sdio.h"
+#include "ch32f20x_spi.h"
+#include "ch32f20x_tim.h"
+#include "ch32f20x_usart.h"
+#include "ch32f20x_wwdg.h"
+#include "ch32f20x_it.h"
+#include "ch32f20x_misc.h"
+
+#endif /* __CH32F20x_CONF_H */
diff --git a/hw/bsp/ch32f20x/ch32f20x_it.c b/hw/bsp/ch32f20x/ch32f20x_it.c
new file mode 100644
index 000000000..94e28e380
--- /dev/null
+++ b/hw/bsp/ch32f20x/ch32f20x_it.c
@@ -0,0 +1,35 @@
+#include "ch32f20x_it.h"
+
+#include "ch32f20x.h"
+
+/* -------------------------------------------------------------------------- */
+
+void NMI_Handler(void) {
+
+}
+
+/* -------------------------------------------------------------------------- */
+
+void MemManage_Handler(void) {
+
+}
+
+/* -------------------------------------------------------------------------- */
+
+void BusFault_Handler(void) {
+
+}
+
+/* -------------------------------------------------------------------------- */
+
+void UsageFault_Handler(void) {
+
+}
+
+/* -------------------------------------------------------------------------- */
+
+void DebugMon_Handler(void) {
+
+}
+
+/* -------------------------------------------------------------------------- */
diff --git a/hw/bsp/ch32f20x/ch32f20x_it.h b/hw/bsp/ch32f20x/ch32f20x_it.h
new file mode 100644
index 000000000..34f3bbf96
--- /dev/null
+++ b/hw/bsp/ch32f20x/ch32f20x_it.h
@@ -0,0 +1,25 @@
+/********************************** (C) COPYRIGHT *******************************
+* File Name : ch32f20x_it.h
+* Author : WCH
+* Version : V1.0.0
+* Date : 2021/08/08
+* Description : This file contains the headers of the interrupt handlers.
+*********************************************************************************
+* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
+* Attention: This software (modified or not) and binary are used for
+* microcontroller manufactured by Nanjing Qinheng Microelectronics.
+*******************************************************************************/
+#ifndef __CH32F20xIT_H
+#define __CH32F20xIT_H
+
+#include "ch32f20x.h"
+
+void NMI_Handler(void);
+void HardFault_Handler(void);
+void MemManage_Handler(void);
+void BusFault_Handler(void);
+void UsageFault_Handler(void);
+void DebugMon_Handler(void);
+
+
+#endif /* __CH32F20xIT_H */
diff --git a/hw/bsp/ch32f20x/core_cm3.h b/hw/bsp/ch32f20x/core_cm3.h
new file mode 100644
index 000000000..c35a4eec3
--- /dev/null
+++ b/hw/bsp/ch32f20x/core_cm3.h
@@ -0,0 +1,11 @@
+/* There is core_cm3.h wrapper just to avoid warnings from CMSIS headers */
+/* if you want use original file add to make file:
+ INC += \
+ $(TOP)/$(CH32F20X_SDK_SRC)/CMSIS
+*/
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+
+#include <../../CMSIS/core_cm3.h>
+
+#pragma GCC diagnostic pop
diff --git a/hw/bsp/ch32f20x/debug_uart.c b/hw/bsp/ch32f20x/debug_uart.c
new file mode 100644
index 000000000..a595eb6f7
--- /dev/null
+++ b/hw/bsp/ch32f20x/debug_uart.c
@@ -0,0 +1,105 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Denis Krasutski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+#include
+
+#include "board.h"
+#include "debug_uart.h"
+
+#define UART_RINGBUFFER_SIZE_TX 64
+#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX-1)
+
+static char tx_buf[UART_RINGBUFFER_SIZE_TX];
+static unsigned int tx_produce = 0;
+static volatile unsigned int tx_consume = 0;
+
+void UART_DEV_IRQHandler(void)
+{
+ if(USART_GetITStatus(UART_DEV, USART_IT_TC) != RESET) {
+ USART_ClearITPendingBit(UART_DEV, USART_IT_TC);
+
+ if(tx_consume != tx_produce) {
+ USART_SendData(UART_DEV, tx_buf[tx_consume]);
+ tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX;
+ }
+ }
+}
+
+void uart_write(char c)
+{
+ unsigned int tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX;
+
+ NVIC_DisableIRQ(UART_DEV_IRQn);
+ if((tx_consume != tx_produce) || (USART_GetFlagStatus(UART_DEV, USART_FLAG_TXE) == RESET)) {
+ tx_buf[tx_produce] = c;
+ tx_produce = tx_produce_next;
+ } else {
+ USART_SendData(UART_DEV, c);
+ }
+ NVIC_EnableIRQ(UART_DEV_IRQn);
+}
+
+void uart_sync(void)
+{
+ while(tx_consume != tx_produce) {
+ //Waiting for transfer complete
+ }
+}
+
+void usart_printf_init(uint32_t baudrate)
+{
+ tx_produce = 0;
+ tx_consume = 0;
+
+ UART_DEV_CLK_EN();
+
+ GPIO_InitTypeDef gpio_config = {
+ .GPIO_Pin = UART_DEV_TX_PIN,
+ .GPIO_Speed = GPIO_Speed_50MHz,
+ .GPIO_Mode = GPIO_Mode_AF_PP,
+ };
+ GPIO_Init(UART_DEV_GPIO_PORT, &gpio_config);
+
+ USART_InitTypeDef uart_config = {
+ .USART_BaudRate = baudrate,
+ .USART_WordLength = USART_WordLength_8b,
+ .USART_StopBits = USART_StopBits_1,
+ .USART_Parity = USART_Parity_No,
+ .USART_HardwareFlowControl = USART_HardwareFlowControl_None,
+ .USART_Mode = USART_Mode_Tx,
+ };
+
+ USART_Init(UART_DEV, &uart_config);
+ USART_ITConfig(UART_DEV, USART_IT_TC, ENABLE);
+ USART_Cmd(UART_DEV, ENABLE);
+
+ NVIC_InitTypeDef nvic_config = {
+ .NVIC_IRQChannel = UART_DEV_IRQn,
+ .NVIC_IRQChannelPreemptionPriority = 1,
+ .NVIC_IRQChannelSubPriority = 3,
+ .NVIC_IRQChannelCmd = ENABLE,
+ };
+ NVIC_Init(&nvic_config);
+}
diff --git a/hw/bsp/ch32f20x/debug_uart.h b/hw/bsp/ch32f20x/debug_uart.h
new file mode 100644
index 000000000..10284cf6f
--- /dev/null
+++ b/hw/bsp/ch32f20x/debug_uart.h
@@ -0,0 +1,31 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Denis Krasutski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include
+
+void uart_write(char c);
+void uart_sync(void);
+void usart_printf_init(uint32_t baudrate);
diff --git a/hw/bsp/ch32f20x/family.c b/hw/bsp/ch32f20x/family.c
new file mode 100644
index 000000000..9717832d6
--- /dev/null
+++ b/hw/bsp/ch32f20x/family.c
@@ -0,0 +1,141 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Denis Krasutski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "stdio.h"
+#include "debug_uart.h"
+
+#include "ch32f20x.h"
+
+#include "bsp/board_api.h"
+#include "board.h"
+
+//--------------------------------------------------------------------+
+// Forward USB interrupt events to TinyUSB IRQ Handler
+//--------------------------------------------------------------------+
+
+void USBHS_IRQHandler(void)
+{
+ tud_int_handler(0);
+}
+
+void board_init(void) {
+
+ /* Disable interrupts during init */
+ __disable_irq();
+
+#if CFG_TUSB_OS == OPT_OS_NONE
+ SysTick_Config(SystemCoreClock / 1000);
+#endif
+
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+ // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
+ NVIC_SetPriority(USBHS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
+#endif
+
+ usart_printf_init(115200);
+
+ // USB HS Clock config
+ RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_USBPHY);
+ RCC_USBHSPLLCLKConfig(RCC_HSBHSPLLCLKSource_HSE);
+ RCC_USBHSConfig(RCC_USBPLL_Div2);
+ RCC_USBHSPLLCKREFCLKConfig(RCC_USBHSPLLCKREFCLK_4M);
+ RCC_USBHSPHYPLLALIVEcmd(ENABLE);
+ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE);
+
+ // LED
+ LED_CLOCK_EN();
+ GPIO_InitTypeDef led_pin_config = {
+ .GPIO_Pin = LED_PIN,
+ .GPIO_Mode = GPIO_Mode_Out_OD,
+ .GPIO_Speed = GPIO_Speed_50MHz,
+ };
+ GPIO_Init(LED_PORT, &led_pin_config);
+
+ // Button
+ BUTTON_CLOCK_EN();
+ GPIO_InitTypeDef button_pin_config = {
+ .GPIO_Pin = BUTTON_PIN,
+ .GPIO_Mode = GPIO_Mode_IPU,
+ .GPIO_Speed = GPIO_Speed_50MHz,
+ };
+ GPIO_Init(BUTTON_PORT, &button_pin_config);
+
+ /* Enable interrupts globally */
+ __enable_irq();
+}
+
+#if CFG_TUSB_OS == OPT_OS_NONE
+
+volatile uint32_t system_ticks = 0;
+
+void SysTick_Handler(void)
+{
+ system_ticks++;
+}
+
+uint32_t board_millis(void)
+{
+ return system_ticks;
+}
+
+#endif
+
+void HardFault_Handler(void)
+{
+ __asm("BKPT #0\n");
+}
+
+//--------------------------------------------------------------------+
+// Board porting API
+//--------------------------------------------------------------------+
+
+void board_led_write(bool state)
+{
+ GPIO_WriteBit(LED_PORT, LED_PIN, state);
+}
+
+uint32_t board_button_read(void)
+{
+ return BUTTON_STATE_ACTIVE == GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN);
+}
+
+int board_uart_read(uint8_t *buf, int len)
+{
+ (void) buf;
+ (void) len;
+ return 0;
+}
+
+int board_uart_write(void const *buf, int len)
+{
+ int txsize = len;
+ while ( txsize-- )
+ {
+ uart_write(*(uint8_t const*) buf);
+ buf++;
+ }
+ return len;
+}
diff --git a/hw/bsp/ch32f20x/family.mk b/hw/bsp/ch32f20x/family.mk
new file mode 100644
index 000000000..c08451b9c
--- /dev/null
+++ b/hw/bsp/ch32f20x/family.mk
@@ -0,0 +1,30 @@
+# Submodules
+CH32F20X_SDK = hw/mcu/wch/ch32f20x
+DEPS_SUBMODULES += $(CH32F20X_SDK)
+
+# WCH-SDK paths
+CH32F20X_SDK_SRC = $(CH32F20X_SDK)/EVT/EXAM/SRC
+
+include $(TOP)/$(BOARD_PATH)/board.mk
+
+CPU_CORE ?= cortex-m3
+
+CFLAGS += \
+ -DCFG_TUSB_MCU=OPT_MCU_CH32F20X \
+ -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED
+
+SRC_C += \
+ src/portable/wch/dcd_ch32_usbhs.c \
+ $(CH32F20X_SDK_SRC)/StdPeriphDriver/src/ch32f20x_gpio.c \
+ $(CH32F20X_SDK_SRC)/StdPeriphDriver/src/ch32f20x_misc.c \
+ $(CH32F20X_SDK_SRC)/StdPeriphDriver/src/ch32f20x_rcc.c \
+ $(CH32F20X_SDK_SRC)/StdPeriphDriver/src/ch32f20x_usart.c
+
+INC += \
+ $(TOP)/$(BOARD_PATH) \
+ $(TOP)/$(CH32F20X_SDK_SRC)/StdPeriphDriver/inc
+
+# For freeRTOS port source
+FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM3
+
+flash: flash-stlink
diff --git a/hw/bsp/ch32f20x/startup_gcc_ch32f20x_d8c.s b/hw/bsp/ch32f20x/startup_gcc_ch32f20x_d8c.s
new file mode 100644
index 000000000..2ecac2ac1
--- /dev/null
+++ b/hw/bsp/ch32f20x/startup_gcc_ch32f20x_d8c.s
@@ -0,0 +1,493 @@
+/**
+ ******************************************************************************
+ * @file startup_gcc_ch32f20x_d8c.s
+ * @author Denis Krasutski
+ * @brief CH32F205 Devices vector table
+ * This module performs:
+ * - Set the initial SP
+ * - Set the initial PC == Reset_Handler,
+ * - Set the vector table entries with the exceptions ISR address
+ * - Branches to main in the C library (which eventually
+ * calls main()).
+ * After Reset the Cortex-M3 processor is in Thread mode,
+ * priority is Privileged, and the Stack is set to Main.
+ ******************************************************************************
+ */
+
+.syntax unified
+.cpu cortex-m3
+.thumb
+.global g_pfnVectors
+.global Default_Handler
+
+/* start address for the initialization values of the .data section. defined in linker script */
+.word _sidata
+/* start address for the .data section. defined in linker script */
+.word _sdata
+/* end address for the .data section. defined in linker script */
+.word _edata
+/* start address for the .bss section. defined in linker script */
+.word _sbss
+/* end address for the .bss section. defined in linker script */
+.word _ebss
+
+.section .text.Reset_Handler
+.weak Reset_Handler
+.type Reset_Handler, %function
+Reset_Handler:
+ /* set stack pointer */
+ ldr sp, =_estack
+ /* Call the clock system initialization function.*/
+ bl SystemInit
+ /* Copy the data segment initializers from flash to SRAM */
+ ldr r0, =_sdata
+ ldr r1, =_edata
+ ldr r2, =_sidata
+ movs r3, #0
+ b LoopCopyDataInit
+CopyDataInit:
+ ldr r4, [r2, r3]
+ str r4, [r0, r3]
+ adds r3, r3, #4
+LoopCopyDataInit:
+ adds r4, r0, r3
+ cmp r4, r1
+ bcc CopyDataInit
+
+ /* Zero fill the bss segment. */
+ ldr r2, =_sbss
+ ldr r4, =_ebss
+ movs r3, #0
+ b LoopFillZerobss
+FillZerobss:
+ str r3, [r2]
+ adds r2, r2, #4
+LoopFillZerobss:
+ cmp r2, r4
+ bcc FillZerobss
+ /* Call static constructors */
+ bl __libc_init_array
+ /* Call the application's entry point.*/
+ bl main
+ bx lr
+ .size Reset_Handler, .-Reset_Handler
+
+.section .text.Default_Handler,"ax",%progbits
+Default_Handler:
+Infinite_Loop:
+ b Infinite_Loop
+ .size Default_Handler, .-Default_Handler
+
+/******************************************************************************
+*
+* The minimal vector table for a Cortex M3. Note that the proper constructs
+* must be placed on this to ensure that it ends up at physical address
+* 0x0000.0000.
+*
+*******************************************************************************/
+ .section .isr_vector,"a",%progbits
+ .type g_pfnVectors, %object
+ .size g_pfnVectors, .-g_pfnVectors
+
+g_pfnVectors:
+ .word _estack
+ .word Reset_Handler
+ .word NMI_Handler
+ .word HardFault_Handler
+ .word MemManage_Handler
+ .word BusFault_Handler
+ .word UsageFault_Handler
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word SVC_Handler
+ .word DebugMon_Handler
+ .word 0
+ .word PendSV_Handler
+ .word SysTick_Handler
+
+/*******************************************************************************
+ External Interrupts
+*******************************************************************************/
+.word WWDG_IRQHandler
+.word PVD_IRQHandler
+.word TAMPER_IRQHandler
+.word RTC_IRQHandler
+.word FLASH_IRQHandler
+.word RCC_IRQHandler
+.word EXTI0_IRQHandler
+.word EXTI1_IRQHandler
+.word EXTI2_IRQHandler
+.word EXTI3_IRQHandler
+.word EXTI4_IRQHandler
+.word DMA1_Channel1_IRQHandler
+.word DMA1_Channel2_IRQHandler
+.word DMA1_Channel3_IRQHandler
+.word DMA1_Channel4_IRQHandler
+.word DMA1_Channel5_IRQHandler
+.word DMA1_Channel6_IRQHandler
+.word DMA1_Channel7_IRQHandler
+.word ADC1_2_IRQHandler
+.word USB_HP_CAN1_TX_IRQHandler
+.word USB_LP_CAN1_RX0_IRQHandler
+.word CAN1_RX1_IRQHandler
+.word CAN1_SCE_IRQHandler
+.word EXTI9_5_IRQHandler
+.word TIM1_BRK_IRQHandler
+.word TIM1_UP_IRQHandler
+.word TIM1_TRG_COM_IRQHandler
+.word TIM1_CC_IRQHandler
+.word TIM2_IRQHandler
+.word TIM3_IRQHandler
+.word TIM4_IRQHandler
+.word I2C1_EV_IRQHandler
+.word I2C1_ER_IRQHandler
+.word I2C2_EV_IRQHandler
+.word I2C2_ER_IRQHandler
+.word SPI1_IRQHandler
+.word SPI2_IRQHandler
+.word USART1_IRQHandler
+.word USART2_IRQHandler
+.word USART3_IRQHandler
+.word EXTI15_10_IRQHandler
+.word RTCAlarm_IRQHandler
+.word 0
+.word TIM8_BRK_IRQHandler
+.word TIM8_UP_IRQHandler
+.word TIM8_TRG_COM_IRQHandler
+.word TIM8_CC_IRQHandler
+.word RNG_IRQHandler
+.word FSMC_IRQHandler
+.word SDIO_IRQHandler
+.word TIM5_IRQHandler
+.word SPI3_IRQHandler
+.word UART4_IRQHandler
+.word UART5_IRQHandler
+.word TIM6_IRQHandler
+.word TIM7_IRQHandler
+.word DMA2_Channel1_IRQHandler
+.word DMA2_Channel2_IRQHandler
+.word DMA2_Channel3_IRQHandler
+.word DMA2_Channel4_IRQHandler
+.word DMA2_Channel5_IRQHandler
+.word ETH_IRQHandler
+.word ETH_WKUP_IRQHandler
+.word CAN2_TX_IRQHandler
+.word CAN2_RX0_IRQHandler
+.word CAN2_RX1_IRQHandler
+.word CAN2_SCE_IRQHandler
+.word OTG_FS_IRQHandler
+.word USBHSWakeup_IRQHandler
+.word USBHS_IRQHandler
+.word DVP_IRQHandler
+.word UART6_IRQHandler
+.word UART7_IRQHandler
+.word UART8_IRQHandler
+.word TIM9_BRK_IRQHandler
+.word TIM9_UP_IRQHandler
+.word TIM9_TRG_COM_IRQHandler
+.word TIM9_CC_IRQHandler
+.word TIM10_BRK_IRQHandler
+.word TIM10_UP_IRQHandler
+.word TIM10_TRG_COM_IRQHandler
+.word TIM10_CC_IRQHandler
+.word DMA2_Channel6_IRQHandler
+.word DMA2_Channel7_IRQHandler
+.word DMA2_Channel8_IRQHandler
+.word DMA2_Channel9_IRQHandler
+.word DMA2_Channel10_IRQHandler
+.word DMA2_Channel11_IRQHandler
+
+/*******************************************************************************
+*
+* Provide weak aliases
+*
+*******************************************************************************/
+.weak NMI_Handler
+.thumb_set NMI_Handler,Default_Handler
+
+.weak HardFault_Handler
+.thumb_set HardFault_Handler,Default_Handler
+
+.weak MemManage_Handler
+.thumb_set MemManage_Handler,Default_Handler
+
+.weak BusFault_Handler
+.thumb_set BusFault_Handler,Default_Handler
+
+.weak UsageFault_Handler
+.thumb_set UsageFault_Handler,Default_Handler
+
+.weak SVC_Handler
+.thumb_set SVC_Handler,Default_Handler
+
+.weak DebugMon_Handler
+.thumb_set DebugMon_Handler,Default_Handler
+
+.weak PendSV_Handler
+.thumb_set PendSV_Handler,Default_Handler
+
+.weak SysTick_Handler
+.thumb_set SysTick_Handler,Default_Handler
+
+.weak WWDG_IRQHandler
+.thumb_set WWDG_IRQHandler,Default_Handler
+
+.weak PVD_IRQHandler
+.thumb_set PVD_IRQHandler,Default_Handler
+
+.weak TAMPER_IRQHandler
+.thumb_set TAMPER_IRQHandler,Default_Handler
+
+.weak RTC_IRQHandler
+.thumb_set RTC_IRQHandler,Default_Handler
+
+.weak FLASH_IRQHandler
+.thumb_set FLASH_IRQHandler,Default_Handler
+
+.weak RCC_IRQHandler
+.thumb_set RCC_IRQHandler,Default_Handler
+
+.weak EXTI0_IRQHandler
+.thumb_set EXTI0_IRQHandler,Default_Handler
+
+.weak EXTI1_IRQHandler
+.thumb_set EXTI1_IRQHandler,Default_Handler
+
+.weak EXTI2_IRQHandler
+.thumb_set EXTI2_IRQHandler,Default_Handler
+
+.weak EXTI3_IRQHandler
+.thumb_set EXTI3_IRQHandler,Default_Handler
+
+.weak EXTI4_IRQHandler
+.thumb_set EXTI4_IRQHandler,Default_Handler
+
+.weak DMA1_Channel1_IRQHandler
+.thumb_set DMA1_Channel1_IRQHandler,Default_Handler
+
+.weak DMA1_Channel2_IRQHandler
+.thumb_set DMA1_Channel2_IRQHandler,Default_Handler
+
+.weak DMA1_Channel3_IRQHandler
+.thumb_set DMA1_Channel3_IRQHandler,Default_Handler
+
+.weak DMA1_Channel4_IRQHandler
+.thumb_set DMA1_Channel4_IRQHandler,Default_Handler
+
+.weak DMA1_Channel5_IRQHandler
+.thumb_set DMA1_Channel5_IRQHandler,Default_Handler
+
+.weak DMA1_Channel6_IRQHandler
+.thumb_set DMA1_Channel6_IRQHandler,Default_Handler
+
+.weak DMA1_Channel7_IRQHandler
+.thumb_set DMA1_Channel7_IRQHandler,Default_Handler
+
+.weak ADC1_2_IRQHandler
+.thumb_set ADC1_2_IRQHandler,Default_Handler
+
+.weak USB_HP_CAN1_TX_IRQHandler
+.thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler
+
+.weak USB_LP_CAN1_RX0_IRQHandler
+.thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler
+
+.weak CAN1_RX1_IRQHandler
+.thumb_set CAN1_RX1_IRQHandler,Default_Handler
+
+.weak CAN1_SCE_IRQHandler
+.thumb_set CAN1_SCE_IRQHandler,Default_Handler
+
+.weak EXTI9_5_IRQHandler
+.thumb_set EXTI9_5_IRQHandler,Default_Handler
+
+.weak TIM1_BRK_IRQHandler
+.thumb_set TIM1_BRK_IRQHandler,Default_Handler
+
+.weak TIM1_UP_IRQHandler
+.thumb_set TIM1_UP_IRQHandler,Default_Handler
+
+.weak TIM1_TRG_COM_IRQHandler
+.thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler
+
+.weak TIM1_CC_IRQHandler
+.thumb_set TIM1_CC_IRQHandler,Default_Handler
+
+.weak TIM2_IRQHandler
+.thumb_set TIM2_IRQHandler,Default_Handler
+
+.weak TIM3_IRQHandler
+.thumb_set TIM3_IRQHandler,Default_Handler
+
+.weak TIM4_IRQHandler
+.thumb_set TIM4_IRQHandler,Default_Handler
+
+.weak I2C1_EV_IRQHandler
+.thumb_set I2C1_EV_IRQHandler,Default_Handler
+
+.weak I2C1_ER_IRQHandler
+.thumb_set I2C1_ER_IRQHandler,Default_Handler
+
+.weak I2C2_EV_IRQHandler
+.thumb_set I2C2_EV_IRQHandler,Default_Handler
+
+.weak I2C2_ER_IRQHandler
+.thumb_set I2C2_ER_IRQHandler,Default_Handler
+
+.weak SPI1_IRQHandler
+.thumb_set SPI1_IRQHandler,Default_Handler
+
+.weak SPI2_IRQHandler
+.thumb_set SPI2_IRQHandler,Default_Handler
+
+.weak USART1_IRQHandler
+.thumb_set USART1_IRQHandler,Default_Handler
+
+.weak USART2_IRQHandler
+.thumb_set USART2_IRQHandler,Default_Handler
+
+.weak USART3_IRQHandler
+.thumb_set USART3_IRQHandler,Default_Handler
+
+.weak EXTI15_10_IRQHandler
+.thumb_set EXTI15_10_IRQHandler,Default_Handler
+
+.weak RTCAlarm_IRQHandler
+.thumb_set RTCAlarm_IRQHandler,Default_Handler
+
+.weak TIM8_BRK_IRQHandler
+.thumb_set TIM8_BRK_IRQHandler,Default_Handler
+
+.weak TIM8_UP_IRQHandler
+.thumb_set TIM8_UP_IRQHandler,Default_Handler
+
+.weak TIM8_TRG_COM_IRQHandler
+.thumb_set TIM8_TRG_COM_IRQHandler,Default_Handler
+
+.weak TIM8_CC_IRQHandler
+.thumb_set TIM8_CC_IRQHandler,Default_Handler
+
+.weak RNG_IRQHandler
+.thumb_set RNG_IRQHandler,Default_Handler
+
+.weak FSMC_IRQHandler
+.thumb_set FSMC_IRQHandler,Default_Handler
+
+.weak SDIO_IRQHandler
+.thumb_set SDIO_IRQHandler,Default_Handler
+
+.weak TIM5_IRQHandler
+.thumb_set TIM5_IRQHandler,Default_Handler
+
+.weak SPI3_IRQHandler
+.thumb_set SPI3_IRQHandler,Default_Handler
+
+.weak UART4_IRQHandler
+.thumb_set UART4_IRQHandler,Default_Handler
+
+.weak UART5_IRQHandler
+.thumb_set UART5_IRQHandler,Default_Handler
+
+.weak TIM6_IRQHandler
+.thumb_set TIM6_IRQHandler,Default_Handler
+
+.weak TIM7_IRQHandler
+.thumb_set TIM7_IRQHandler,Default_Handler
+
+.weak DMA2_Channel1_IRQHandler
+.thumb_set DMA2_Channel1_IRQHandler,Default_Handler
+
+.weak DMA2_Channel2_IRQHandler
+.thumb_set DMA2_Channel2_IRQHandler,Default_Handler
+
+.weak DMA2_Channel3_IRQHandler
+.thumb_set DMA2_Channel3_IRQHandler,Default_Handler
+
+.weak DMA2_Channel4_IRQHandler
+.thumb_set DMA2_Channel4_IRQHandler,Default_Handler
+
+.weak DMA2_Channel5_IRQHandler
+.thumb_set DMA2_Channel5_IRQHandler,Default_Handler
+
+.weak ETH_IRQHandler
+.thumb_set ETH_IRQHandler,Default_Handler
+
+.weak ETH_WKUP_IRQHandler
+.thumb_set ETH_WKUP_IRQHandler,Default_Handler
+
+.weak CAN2_TX_IRQHandler
+.thumb_set CAN2_TX_IRQHandler,Default_Handler
+
+.weak CAN2_RX0_IRQHandler
+.thumb_set CAN2_RX0_IRQHandler,Default_Handler
+
+.weak CAN2_RX1_IRQHandler
+.thumb_set CAN2_RX1_IRQHandler,Default_Handler
+
+.weak CAN2_SCE_IRQHandler
+.thumb_set CAN2_SCE_IRQHandler,Default_Handler
+
+.weak OTG_FS_IRQHandler
+.thumb_set OTG_FS_IRQHandler,Default_Handler
+
+.weak USBHSWakeup_IRQHandler
+.thumb_set USBHSWakeup_IRQHandler,Default_Handler
+
+.weak USBHS_IRQHandler
+.thumb_set USBHS_IRQHandler,Default_Handler
+
+.weak DVP_IRQHandler
+.thumb_set DVP_IRQHandler,Default_Handler
+
+.weak UART6_IRQHandler
+.thumb_set UART6_IRQHandler,Default_Handler
+
+.weak UART7_IRQHandler
+.thumb_set UART7_IRQHandler,Default_Handler
+
+.weak UART8_IRQHandler
+.thumb_set UART8_IRQHandler,Default_Handler
+
+.weak TIM9_BRK_IRQHandler
+.thumb_set TIM9_BRK_IRQHandler,Default_Handler
+
+.weak TIM9_UP_IRQHandler
+.thumb_set TIM9_UP_IRQHandler,Default_Handler
+
+.weak TIM9_TRG_COM_IRQHandler
+.thumb_set TIM9_TRG_COM_IRQHandler,Default_Handler
+
+.weak TIM9_CC_IRQHandler
+.thumb_set TIM9_CC_IRQHandler,Default_Handler
+
+.weak TIM10_BRK_IRQHandler
+.thumb_set TIM10_BRK_IRQHandler,Default_Handler
+
+.weak TIM10_UP_IRQHandler
+.thumb_set TIM10_UP_IRQHandler,Default_Handler
+
+.weak TIM10_TRG_COM_IRQHandler
+.thumb_set TIM10_TRG_COM_IRQHandler,Default_Handler
+
+.weak TIM10_CC_IRQHandler
+.thumb_set TIM10_CC_IRQHandler,Default_Handler
+
+.weak DMA2_Channel6_IRQHandler
+.thumb_set DMA2_Channel6_IRQHandler,Default_Handler
+
+.weak DMA2_Channel7_IRQHandler
+.thumb_set DMA2_Channel7_IRQHandler,Default_Handler
+
+.weak DMA2_Channel8_IRQHandler
+.thumb_set DMA2_Channel8_IRQHandler,Default_Handler
+
+.weak DMA2_Channel9_IRQHandler
+.thumb_set DMA2_Channel9_IRQHandler,Default_Handler
+
+.weak DMA2_Channel10_IRQHandler
+.thumb_set DMA2_Channel10_IRQHandler,Default_Handler
+
+.weak DMA2_Channel11_IRQHandler
+.thumb_set DMA2_Channel11_IRQHandler,Default_Handler
diff --git a/hw/bsp/ch32f20x/system_ch32f20x.c b/hw/bsp/ch32f20x/system_ch32f20x.c
new file mode 100644
index 000000000..0a59b9287
--- /dev/null
+++ b/hw/bsp/ch32f20x/system_ch32f20x.c
@@ -0,0 +1,1122 @@
+/********************************** (C) COPYRIGHT *******************************
+* File Name : system_ch32f20x.c
+* Author : WCH
+* Version : V1.0.0
+* Date : 2021/08/08
+* Description : CH32F20x Device Peripheral Access Layer System Source File.
+* For CH32F208 HSE = 32Mhz
+* For others HSE = 8Mhz
+*********************************************************************************
+* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
+* Attention: This software (modified or not) and binary are used for
+* microcontroller manufactured by Nanjing Qinheng Microelectronics.
+*******************************************************************************/
+#include "ch32f20x.h"
+
+/*
+* Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
+* reset the HSI is used as SYSCLK source).
+* If none of the define below is enabled, the HSI is used as System clock source.
+*/
+
+//#define SYSCLK_FREQ_HSE HSE_VALUE
+//#define SYSCLK_FREQ_48MHz_HSE 48000000
+//#define SYSCLK_FREQ_56MHz_HSE 56000000
+//#define SYSCLK_FREQ_72MHz_HSE 72000000
+#define SYSCLK_FREQ_96MHz_HSE 96000000
+//#define SYSCLK_FREQ_120MHz_HSE 120000000
+//#define SYSCLK_FREQ_144MHz_HSE 144000000
+//#define SYSCLK_FREQ_HSI HSI_VALUE
+//#define SYSCLK_FREQ_48MHz_HSI 48000000
+//#define SYSCLK_FREQ_56MHz_HSI 56000000
+//#define SYSCLK_FREQ_72MHz_HSI 72000000
+//#define SYSCLK_FREQ_96MHz_HSI 96000000
+//#define SYSCLK_FREQ_120MHz_HSI 120000000
+//#define SYSCLK_FREQ_144MHz_HSI 144000000
+
+
+/* Uncomment the following line if you need to relocate your vector Table in Internal SRAM */
+/* #define VECT_TAB_SRAM */
+
+/* Vector Table base offset field This value must be a multiple of 0x200 */
+#define VECT_TAB_OFFSET 0x0
+
+/* Clock Definitions */
+#ifdef SYSCLK_FREQ_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_48MHz_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_56MHz_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_72MHz_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_96MHz_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_120MHz_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_144MHz_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_48MHz_HSI
+uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSI; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_56MHz_HSI
+uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSI; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_72MHz_HSI
+uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSI; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_96MHz_HSI
+uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSI; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_120MHz_HSI
+uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSI; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_144MHz_HSI
+uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_HSI; /* System Clock Frequency (Core Clock) */
+#else
+uint32_t SystemCoreClock = HSI_VALUE; /* System Clock Frequency (Core Clock) */
+
+#endif
+
+__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
+
+/* system_private_function_proto_types */
+static void SetSysClock( void );
+
+#ifdef SYSCLK_FREQ_HSE
+static void SetSysClockToHSE( void );
+#elif defined SYSCLK_FREQ_48MHz_HSE
+static void SetSysClockTo48_HSE( void );
+#elif defined SYSCLK_FREQ_56MHz_HSE
+static void SetSysClockTo56_HSE( void );
+#elif defined SYSCLK_FREQ_72MHz_HSE
+static void SetSysClockTo72_HSE( void );
+#elif defined SYSCLK_FREQ_96MHz_HSE
+static void SetSysClockTo96_HSE( void );
+#elif defined SYSCLK_FREQ_120MHz_HSE
+static void SetSysClockTo120_HSE( void );
+#elif defined SYSCLK_FREQ_144MHz_HSE
+static void SetSysClockTo144_HSE( void );
+#elif defined SYSCLK_FREQ_48MHz_HSI
+static void SetSysClockTo48_HSI( void );
+#elif defined SYSCLK_FREQ_56MHz_HSI
+static void SetSysClockTo56_HSI( void );
+#elif defined SYSCLK_FREQ_72MHz_HSI
+static void SetSysClockTo72_HSI( void );
+#elif defined SYSCLK_FREQ_96MHz_HSI
+static void SetSysClockTo96_HSI( void );
+#elif defined SYSCLK_FREQ_120MHz_HSI
+static void SetSysClockTo120_HSI( void );
+#elif defined SYSCLK_FREQ_144MHz_HSI
+static void SetSysClockTo144_HSI( void );
+
+#endif
+
+
+/*********************************************************************
+ * @fn SystemInit
+ *
+ * @brief Setup the microcontroller system Initialize the Embedded Flash Interface,
+ * the PLL and update the SystemCoreClock variable.
+ *
+ * @return none
+ */
+void SystemInit( void )
+{
+ RCC->CTLR |= ( uint32_t )0x00000001;
+
+#ifdef CH32F20x_D8C
+ RCC->CFGR0 &= ( uint32_t )0xF8FF0000;
+#else
+ RCC->CFGR0 &= ( uint32_t )0xF0FF0000;
+#endif
+
+ RCC->CTLR &= ( uint32_t )0xFEF6FFFF;
+ RCC->CTLR &= ( uint32_t )0xFFFBFFFF;
+ RCC->CFGR0 &= ( uint32_t )0xFF80FFFF;
+#ifdef CH32F20x_D8C
+ RCC->CTLR &= ( uint32_t )0xEBFFFFFF;
+ RCC->INTR = 0x00FF0000;
+ RCC->CFGR2 = 0x00000000;
+#else
+ RCC->INTR = 0x009F0000;
+#endif
+
+ SetSysClock();
+
+#ifdef VECT_TAB_SRAM
+ SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
+#else
+ SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
+#endif
+}
+
+/*********************************************************************
+ * @fn SystemCoreClockUpdate
+ *
+ * @brief Update SystemCoreClock variable according to Clock Register Values.
+ *
+ * @return none
+ */
+void SystemCoreClockUpdate( void )
+{
+ uint32_t tmp = 0, pllmull = 0, pllsource = 0;
+ uint8_t Pll_6_5 = 0;
+
+#if defined (CH32F20x_D8C)
+ uint8_t Pll2mull = 0;
+
+#endif
+
+ tmp = RCC->CFGR0 & RCC_SWS;
+
+ switch( tmp )
+ {
+ case 0x00:
+ SystemCoreClock = HSI_VALUE;
+ break;
+ case 0x04:
+ SystemCoreClock = HSE_VALUE;
+ break;
+ case 0x08:
+ pllmull = RCC->CFGR0 & RCC_PLLMULL;
+ pllsource = RCC->CFGR0 & RCC_PLLSRC;
+ pllmull = ( pllmull >> 18 ) + 2;
+
+#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
+ if( pllmull == 17 )
+ {
+ pllmull = 18;
+ }
+#else
+ if( pllmull == 2 )
+ {
+ pllmull = 18;
+ }
+ if( pllmull == 15 )
+ {
+ pllmull = 13; /* *6.5 */
+ Pll_6_5 = 1;
+ }
+ if( pllmull == 16 )
+ {
+ pllmull = 15;
+ }
+ if( pllmull == 17 )
+ {
+ pllmull = 16;
+ }
+#endif
+
+ if( pllsource == 0x00 )
+ {
+ if(EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE) SystemCoreClock = HSI_VALUE * pllmull;
+ else SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
+ }
+ else
+ {
+#if defined (CH32F20x_D8C)
+ if(RCC->CFGR2 & (1<<16)){ /* PLL2 */
+ SystemCoreClock = HSE_VALUE/(((RCC->CFGR2 & 0xF0)>>4) + 1); /* PREDIV2 */
+
+ Pll2mull = (uint8_t)((RCC->CFGR2 & 0xF00)>>8);
+
+ if(Pll2mull == 0) SystemCoreClock = (SystemCoreClock * 5)>>1;
+ else if(Pll2mull == 1) SystemCoreClock = (SystemCoreClock * 25)>>1;
+ else if(Pll2mull == 15) SystemCoreClock = SystemCoreClock * 20;
+ else SystemCoreClock = SystemCoreClock * (Pll2mull + 2);
+
+ SystemCoreClock = SystemCoreClock/((RCC->CFGR2 & 0xF) + 1); /* PREDIV1 */
+ }
+ else{/* HSE */
+ SystemCoreClock = HSE_VALUE/((RCC->CFGR2 & 0xF) + 1); /* PREDIV1 */
+ }
+
+ SystemCoreClock = SystemCoreClock * pllmull;
+#else
+
+#if defined (CH32F20x_D8W)
+ if((RCC->CFGR0 & (3<<22)) == (3<<22))
+ {
+ SystemCoreClock = ((HSE_VALUE>>1)) * pllmull;
+ }
+ else
+#endif
+ if( ( RCC->CFGR0 & RCC_PLLXTPRE ) != ( uint32_t )RESET )
+ {
+#ifdef CH32F20x_D8W
+ SystemCoreClock = ( ( HSE_VALUE >> 2 ) >> 1 ) * pllmull;
+#else
+ SystemCoreClock = ( HSE_VALUE >> 1 ) * pllmull;
+#endif
+ }
+ else
+ {
+#ifdef CH32F20x_D8W
+ SystemCoreClock = ( HSE_VALUE >> 2 ) * pllmull;
+#else
+ SystemCoreClock = HSE_VALUE * pllmull;
+#endif
+
+ }
+#endif
+ }
+
+ if( Pll_6_5 == 1 ) SystemCoreClock = ( SystemCoreClock / 2 );
+
+ break;
+ default:
+ SystemCoreClock = HSI_VALUE;
+ break;
+ }
+
+ tmp = AHBPrescTable[( ( RCC->CFGR0 & RCC_HPRE ) >> 4 )];
+ SystemCoreClock >>= tmp;
+}
+
+
+
+/*********************************************************************
+ * @fn SetSysClock
+ *
+ * @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClock( void )
+{
+#ifdef SYSCLK_FREQ_HSE
+ SetSysClockToHSE();
+#elif defined SYSCLK_FREQ_48MHz_HSE
+ SetSysClockTo48_HSE();
+#elif defined SYSCLK_FREQ_56MHz_HSE
+ SetSysClockTo56_HSE();
+#elif defined SYSCLK_FREQ_72MHz_HSE
+ SetSysClockTo72_HSE();
+#elif defined SYSCLK_FREQ_96MHz_HSE
+ SetSysClockTo96_HSE();
+#elif defined SYSCLK_FREQ_120MHz_HSE
+ SetSysClockTo120_HSE();
+#elif defined SYSCLK_FREQ_144MHz_HSE
+ SetSysClockTo144_HSE();
+#elif defined SYSCLK_FREQ_48MHz_HSI
+ SetSysClockTo48_HSI();
+#elif defined SYSCLK_FREQ_56MHz_HSI
+ SetSysClockTo56_HSI();
+#elif defined SYSCLK_FREQ_72MHz_HSI
+ SetSysClockTo72_HSI();
+#elif defined SYSCLK_FREQ_96MHz_HSI
+ SetSysClockTo96_HSI();
+#elif defined SYSCLK_FREQ_120MHz_HSI
+ SetSysClockTo120_HSI();
+#elif defined SYSCLK_FREQ_144MHz_HSI
+ SetSysClockTo144_HSI();
+
+#endif
+
+ /* If none of the define above is enabled, the HSI is used as System clock
+ * source (default after reset)
+ */
+}
+
+
+#ifdef SYSCLK_FREQ_HSE
+
+/*********************************************************************
+ * @fn SetSysClockToHSE
+ *
+ * @brief Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockToHSE( void )
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+
+ RCC->CTLR |= ( ( uint32_t )RCC_HSEON );
+
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ }
+ while( ( HSEStatus == 0 ) && ( StartUpCounter != HSE_STARTUP_TIMEOUT ) );
+
+ if( ( RCC->CTLR & RCC_HSERDY ) != RESET )
+ {
+ HSEStatus = ( uint32_t )0x01;
+ }
+ else
+ {
+ HSEStatus = ( uint32_t )0x00;
+ }
+
+ if( HSEStatus == ( uint32_t )0x01 )
+ {
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV1;
+
+ /* Select HSE as system clock source
+ * CH32F20x_D6 (HSE=8Mhz)
+ * CH32F20x_D8 (HSE=8Mhz)
+ * CH32F20x_D8W (HSE=32Mhz)
+ */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
+ RCC->CFGR0 |= ( uint32_t )RCC_SW_HSE;
+
+ /* Wait till HSE is used as system clock source */
+ while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x04 )
+ {
+ }
+ }
+ else
+ {
+ /* If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+#elif defined SYSCLK_FREQ_48MHz_HSE
+
+/*********************************************************************
+ * @fn SetSysClockTo48_HSE
+ *
+ * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo48_HSE( void )
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+
+ RCC->CTLR |= ( ( uint32_t )RCC_HSEON );
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ }
+ while( ( HSEStatus == 0 ) && ( StartUpCounter != HSE_STARTUP_TIMEOUT ) );
+
+ if( ( RCC->CTLR & RCC_HSERDY ) != RESET )
+ {
+ HSEStatus = ( uint32_t )0x01;
+ }
+ else
+ {
+ HSEStatus = ( uint32_t )0x00;
+ }
+
+ if( HSEStatus == ( uint32_t )0x01 )
+ {
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
+
+ /* CH32F20x_D6-PLL configuration: PLLCLK = HSE * 6 = 48 MHz (HSE=8Mhz)
+ * CH32F20x_D8-PLL configuration: PLLCLK = HSE * 6 = 48 MHz (HSE=8Mhz)
+ * CH32F20x_D8W-PLL configuration: PLLCLK = HSE/4 * 6 = 48 MHz(HSE=32Mhz)
+ */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL ) );
+
+#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL6 );
+#else
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL6_EXTEN );
+#endif
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
+ RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
+ {
+ }
+ }
+ else
+ {
+ /*
+ * If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+#elif defined SYSCLK_FREQ_56MHz_HSE
+
+/*********************************************************************
+ * @fn SetSysClockTo56_HSE
+ *
+ * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo56_HSE( void )
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+ RCC->CTLR |= ( ( uint32_t )RCC_HSEON );
+
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ }
+ while( ( HSEStatus == 0 ) && ( StartUpCounter != HSE_STARTUP_TIMEOUT ) );
+
+ if( ( RCC->CTLR & RCC_HSERDY ) != RESET )
+ {
+ HSEStatus = ( uint32_t )0x01;
+ }
+ else
+ {
+ HSEStatus = ( uint32_t )0x00;
+ }
+
+ if( HSEStatus == ( uint32_t )0x01 )
+ {
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
+
+ /* CH32F20x_D6-PLL configuration: PLLCLK = HSE * 7 = 56 MHz (HSE=8Mhz)
+ * CH32F20x_D8-PLL configuration: PLLCLK = HSE * 7 = 56 MHz (HSE=8Mhz)
+ * CH32F20x_D8W-PLL configuration: PLLCLK = HSE/4 * 7 = 56 MHz(HSE=32Mhz)
+ */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL ) );
+
+#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL7 );
+#else
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL7_EXTEN );
+#endif
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
+ {
+ }
+
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
+ RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
+ {
+ }
+ }
+ else
+ {
+ /*
+ * If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+#elif defined SYSCLK_FREQ_72MHz_HSE
+
+/*********************************************************************
+ * @fn SetSysClockTo72_HSE
+ *
+ * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo72_HSE( void )
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+ RCC->CTLR |= ( ( uint32_t )RCC_HSEON );
+
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ }
+ while( ( HSEStatus == 0 ) && ( StartUpCounter != HSE_STARTUP_TIMEOUT ) );
+
+ if( ( RCC->CTLR & RCC_HSERDY ) != RESET )
+ {
+ HSEStatus = ( uint32_t )0x01;
+ }
+ else
+ {
+ HSEStatus = ( uint32_t )0x00;
+ }
+
+ if( HSEStatus == ( uint32_t )0x01 )
+ {
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
+
+ /* CH32F20x_D6-PLL configuration: PLLCLK = HSE * 9 = 72 MHz (HSE=8Mhz)
+ * CH32F20x_D8-PLL configuration: PLLCLK = HSE * 9 = 72 MHz (HSE=8Mhz)
+ * CH32F20x_D8W-PLL configuration: PLLCLK = HSE/4 * 9 = 72 MHz(HSE=32Mhz)
+ */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE |
+ RCC_PLLMULL ) );
+
+#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL9 );
+#else
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL9_EXTEN );
+#endif
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
+ RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
+ {
+ }
+ }
+ else
+ {
+ /*
+ * If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+
+#elif defined SYSCLK_FREQ_96MHz_HSE
+
+/*********************************************************************
+ * @fn SetSysClockTo96_HSE
+ *
+ * @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo96_HSE( void )
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+ RCC->CTLR |= ( ( uint32_t )RCC_HSEON );
+
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ }
+ while( ( HSEStatus == 0 ) && ( StartUpCounter != HSE_STARTUP_TIMEOUT ) );
+
+ if( ( RCC->CTLR & RCC_HSERDY ) != RESET )
+ {
+ HSEStatus = ( uint32_t )0x01;
+ }
+ else
+ {
+ HSEStatus = ( uint32_t )0x00;
+ }
+
+ if( HSEStatus == ( uint32_t )0x01 )
+ {
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
+
+ /* CH32F20x_D6-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8Mhz)
+ * CH32F20x_D8-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8Mhz)
+ * CH32F20x_D8W-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz(HSE=32Mhz)
+ */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE |
+ RCC_PLLMULL ) );
+
+#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12 );
+#else
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12_EXTEN );
+#endif
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
+ RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
+ {
+ }
+ }
+ else
+ {
+ /*
+ * If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+
+#elif defined SYSCLK_FREQ_120MHz_HSE
+
+/*********************************************************************
+ * @fn SetSysClockTo120_HSE
+ *
+ * @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo120_HSE(void)
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+ RCC->CTLR |= ((uint32_t)RCC_HSEON);
+
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
+
+ if ((RCC->CTLR & RCC_HSERDY) != RESET)
+ {
+ HSEStatus = (uint32_t)0x01;
+ }
+ else
+ {
+ HSEStatus = (uint32_t)0x00;
+ }
+
+ if (HSEStatus == (uint32_t)0x01)
+ {
+#if defined (CH32F20x_D8W)
+ RCC->CFGR0 |= (uint32_t)(3<<22);
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV2;
+#else
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+#endif
+
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
+
+ /* CH32F20x_D6-PLL configuration: PLLCLK = HSE * 15 = 120 MHz (HSE=8Mhz)
+ * CH32F20x_D8-PLL configuration: PLLCLK = HSE * 15 = 120 MHz (HSE=8Mhz)
+ * CH32F20x_D8W-PLL configuration: PLLCLK = HSE/2 * 15 = 240 MHz(HSE=32Mhz)
+ */
+ RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
+ RCC_PLLMULL));
+
+#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
+ RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL15);
+#else
+ RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL15_EXTEN);
+#endif
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while((RCC->CTLR & RCC_PLLRDY) == 0)
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
+ {
+ }
+ }
+ else
+ {
+ /*
+ * If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+
+
+#elif defined SYSCLK_FREQ_144MHz_HSE
+
+/*********************************************************************
+ * @fn SetSysClockTo144_HSE
+ *
+ * @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo144_HSE( void )
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+ RCC->CTLR |= ( ( uint32_t )RCC_HSEON );
+
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ }
+ while( ( HSEStatus == 0 ) && ( StartUpCounter != HSE_STARTUP_TIMEOUT ) );
+
+ if( ( RCC->CTLR & RCC_HSERDY ) != RESET )
+ {
+ HSEStatus = ( uint32_t )0x01;
+ }
+ else
+ {
+ HSEStatus = ( uint32_t )0x00;
+ }
+
+ if( HSEStatus == ( uint32_t )0x01 )
+ {
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
+
+ /* CH32F20x_D6-PLL configuration: PLLCLK = HSE * 18 = 144 MHz (HSE=8Mhz)
+ * CH32F20x_D8-PLL configuration: PLLCLK = HSE * 18 = 144 MHz (HSE=8Mhz)
+ * CH32F20x_D8W-PLL configuration: PLLCLK = HSE/4 * 18 = 144 MHz(HSE=32Mhz)
+ */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE |
+ RCC_PLLMULL ) );
+
+#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18 );
+#else
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18_EXTEN );
+#endif
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
+ RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
+ {
+ }
+ }
+ else
+ {
+ /*
+ * If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+#elif defined SYSCLK_FREQ_48MHz_HSI
+
+/*********************************************************************
+ * @fn SetSysClockTo48_HSI
+ *
+ * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo48_HSI( void )
+{
+ EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSI * 6 = 48 MHz */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL ) );
+
+#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL6 );
+#else
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL6_EXTEN );
+#endif
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
+ RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
+ {
+ }
+}
+
+#elif defined SYSCLK_FREQ_56MHz_HSI
+
+/*********************************************************************
+ * @fn SetSysClockTo56_HSI
+ *
+ * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo56_HSI( void )
+{
+ EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSI * 7 = 56 MHz */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL ) );
+
+#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL7 );
+#else
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL7_EXTEN );
+#endif
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
+ RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
+ {
+ }
+}
+
+#elif defined SYSCLK_FREQ_72MHz_HSI
+
+/*********************************************************************
+ * @fn SetSysClockTo72_HSI
+ *
+ * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo72_HSI( void )
+{
+ EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSI * 9 = 72 MHz */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL ) );
+
+#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL9 );
+#else
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL9_EXTEN );
+#endif
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
+ RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
+ {
+ }
+}
+
+
+#elif defined SYSCLK_FREQ_96MHz_HSI
+
+/*********************************************************************
+ * @fn SetSysClockTo96_HSI
+ *
+ * @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo96_HSI( void )
+{
+ EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSI * 12 = 96 MHz */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL ) );
+
+#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL12 );
+#else
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL12_EXTEN );
+#endif
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
+ RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
+ {
+ }
+}
+
+
+#elif defined SYSCLK_FREQ_120MHz_HSI
+
+/*********************************************************************
+ * @fn SetSysClockTo120_HSI
+ *
+ * @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo120_HSI(void)
+{
+ EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSI * 15 = 120 MHz */
+ RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
+ RCC_PLLMULL));
+
+#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL15 );
+#else
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL15_EXTEN );
+#endif
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while((RCC->CTLR & RCC_PLLRDY) == 0)
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
+ {
+ }
+}
+
+
+#elif defined SYSCLK_FREQ_144MHz_HSI
+
+/*********************************************************************
+ * @fn SetSysClockTo144_HSI
+ *
+ * @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo144_HSI( void )
+{
+ EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSI * 18 = 144 MHz */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL ) );
+
+#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL18 );
+#else
+ RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL18_EXTEN );
+#endif
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
+ RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
+ {
+ }
+}
+
+
+#endif
diff --git a/hw/bsp/ch32f20x/system_ch32f20x.h b/hw/bsp/ch32f20x/system_ch32f20x.h
new file mode 100644
index 000000000..cf2f5328b
--- /dev/null
+++ b/hw/bsp/ch32f20x/system_ch32f20x.h
@@ -0,0 +1,25 @@
+/********************************** (C) COPYRIGHT *******************************
+* File Name : system_ch32f20x.h
+* Author : WCH
+* Version : V1.0.0
+* Date : 2021/08/08
+* Description : CH32F20x Device Peripheral Access Layer System Header File.
+*******************************************************************************/
+#ifndef __SYSTEM_CH32F20x_H
+#define __SYSTEM_CH32F20x_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+extern uint32_t SystemCoreClock; /* System Clock Frequency (Core Clock) */
+
+/* System_Exported_Functions */
+extern void SystemInit(void);
+extern void SystemCoreClockUpdate(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__CH32F20x_SYSTEM_H */
diff --git a/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.h b/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/board.h
similarity index 99%
rename from hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.h
rename to hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/board.h
index 0eab34916..7b488096e 100644
--- a/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.h
+++ b/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/board.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2023 Ha Thach (tinyusb.org) for Adafruit Industries
diff --git a/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.mk b/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/board.mk
similarity index 100%
rename from hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.mk
rename to hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/board.mk
diff --git a/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.c b/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/debug_uart.c
similarity index 99%
rename from hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.c
rename to hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/debug_uart.c
index 45fc9e3aa..db3551ca7 100644
--- a/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.c
+++ b/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/debug_uart.c
@@ -36,7 +36,7 @@ static unsigned int tx_produce;
static volatile unsigned int tx_consume;
void USART1_IRQHandler(void) __attribute__((naked));
-void USART1_IRQHandler(void) {
+void USART1_IRQHandler(void) {
__asm volatile ("call USART1_IRQHandler_impl; mret");
}
@@ -57,7 +57,7 @@ __attribute__((used)) void USART1_IRQHandler_impl(void)
void uart_write(char c)
{
unsigned int tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX;
-
+
NVIC_DisableIRQ(USART1_IRQn);
if((tx_consume != tx_produce) || (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)) {
tx_buf[tx_produce] = c;
diff --git a/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.h b/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/debug_uart.h
similarity index 100%
rename from hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.h
rename to hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/debug_uart.h
diff --git a/hw/bsp/ch32v307/ch32v307.ld b/hw/bsp/ch32v307/ch32v307.ld
index af7c06615..55bd10cd0 100644
--- a/hw/bsp/ch32v307/ch32v307.ld
+++ b/hw/bsp/ch32v307/ch32v307.ld
@@ -41,7 +41,7 @@ SECTIONS
*(.glue_7t)
*(.gnu.linkonce.t.*)
. = ALIGN(4);
- } >FLASH AT>FLASH
+ } >FLASH AT>FLASH
.fini :
{
@@ -50,31 +50,31 @@ SECTIONS
} >FLASH AT>FLASH
PROVIDE( _etext = . );
- PROVIDE( _eitcm = . );
+ PROVIDE( _eitcm = . );
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
- } >FLASH AT>FLASH
-
+ } >FLASH AT>FLASH
+
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
- } >FLASH AT>FLASH
-
+ } >FLASH AT>FLASH
+
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
- } >FLASH AT>FLASH
-
+ } >FLASH AT>FLASH
+
.ctors :
{
/* gcc uses crtbegin.o to find the start of
@@ -95,8 +95,8 @@ SECTIONS
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
- } >FLASH AT>FLASH
-
+ } >FLASH AT>FLASH
+
.dtors :
{
KEEP (*crtbegin.o(.dtors))
@@ -104,17 +104,17 @@ SECTIONS
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
- } >FLASH AT>FLASH
+ } >FLASH AT>FLASH
.dalign :
{
. = ALIGN(4);
PROVIDE(_data_vma = .);
- } >RAM AT>FLASH
+ } >RAM AT>FLASH
.dlalign :
{
- . = ALIGN(4);
+ . = ALIGN(4);
PROVIDE(_data_lma = .);
} >FLASH AT>FLASH
@@ -145,7 +145,7 @@ SECTIONS
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss*)
- *(.gnu.linkonce.b.*)
+ *(.gnu.linkonce.b.*)
*(COMMON*)
. = ALIGN(4);
PROVIDE( _ebss = .);
@@ -156,15 +156,12 @@ SECTIONS
.stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
{
- PROVIDE( _heap_end = . );
+ PROVIDE( _heap_end = . );
. = ALIGN(4);
PROVIDE(_susrstack = . );
. = . + __stack_size;
PROVIDE( _eusrstack = .);
__freertos_irq_stack_top = .;
- } >RAM
+ } >RAM
}
-
-
-
diff --git a/hw/bsp/ch32v307/ch32v30x_conf.h b/hw/bsp/ch32v307/ch32v30x_conf.h
index 399feaf68..0b86ad390 100644
--- a/hw/bsp/ch32v307/ch32v30x_conf.h
+++ b/hw/bsp/ch32v307/ch32v30x_conf.h
@@ -6,7 +6,7 @@
* Description : Library configuration file.
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* SPDX-License-Identifier: Apache-2.0
-*******************************************************************************/
+*******************************************************************************/
#ifndef __CH32V30x_CONF_H
#define __CH32V30x_CONF_H
@@ -36,8 +36,3 @@
#endif /* __CH32V30x_CONF_H */
-
-
-
-
-
diff --git a/hw/bsp/ch32v307/ch32v30x_it.c b/hw/bsp/ch32v307/ch32v30x_it.c
index d348dd989..c329c5613 100644
--- a/hw/bsp/ch32v307/ch32v30x_it.c
+++ b/hw/bsp/ch32v307/ch32v30x_it.c
@@ -45,5 +45,3 @@ __attribute__((used)) void HardFault_Handler_impl(void)
{
}
}
-
-
diff --git a/hw/bsp/ch32v307/ch32v30x_it.h b/hw/bsp/ch32v307/ch32v30x_it.h
index 42f285edf..f3977a8be 100644
--- a/hw/bsp/ch32v307/ch32v30x_it.h
+++ b/hw/bsp/ch32v307/ch32v30x_it.h
@@ -14,5 +14,3 @@
#endif /* __CH32V30x_IT_H */
-
-
diff --git a/hw/bsp/ch32v307/core_riscv.h b/hw/bsp/ch32v307/core_riscv.h
index 2e94ec683..a7ce10a00 100644
--- a/hw/bsp/ch32v307/core_riscv.h
+++ b/hw/bsp/ch32v307/core_riscv.h
@@ -336,7 +336,7 @@ RV_STATIC_INLINE void NVIC_SystemReset(void)
}
-/* Core_Exported_Functions */
+/* Core_Exported_Functions */
extern uint32_t __get_FFLAGS(void);
extern void __set_FFLAGS(uint32_t value);
extern uint32_t __get_FRM(void);
@@ -377,8 +377,3 @@ extern uint32_t __get_SP(void);
#endif
-
-
-
-
-
diff --git a/hw/bsp/ch32v307/family.c b/hw/bsp/ch32v307/family.c
index d5602c7b4..245fa5674 100644
--- a/hw/bsp/ch32v307/family.c
+++ b/hw/bsp/ch32v307/family.c
@@ -28,7 +28,7 @@
#include "debug_uart.h"
#include "ch32v30x.h"
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "board.h"
//--------------------------------------------------------------------+
diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk
index 15f6724a8..07e57f04c 100644
--- a/hw/bsp/ch32v307/family.mk
+++ b/hw/bsp/ch32v307/family.mk
@@ -28,29 +28,31 @@ CFLAGS += \
-Xlinker --gc-sections \
-DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED
+LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
+
SRC_C += \
- src/portable/wch/ch32v307/dcd_usbhs.c \
+ src/portable/wch/dcd_ch32_usbhs.c \
$(CH32V307_SDK_SRC)/Core/core_riscv.c \
$(CH32V307_SDK_SRC)/Peripheral/src/ch32v30x_gpio.c \
$(CH32V307_SDK_SRC)/Peripheral/src/ch32v30x_misc.c \
$(CH32V307_SDK_SRC)/Peripheral/src/ch32v30x_rcc.c \
- $(CH32V307_SDK_SRC)/Peripheral/src/ch32v30x_usart.c
-
+ $(CH32V307_SDK_SRC)/Peripheral/src/ch32v30x_usart.c
+
SRC_S += \
- $(CH32V307_SDK_SRC)/Startup/startup_ch32v30x_D8C.S
+ $(CH32V307_SDK_SRC)/Startup/startup_ch32v30x_D8C.S
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(CH32V307_SDK_SRC)/Peripheral/inc
# For freeRTOS port source
-FREERTOS_PORT = RISC-V
+FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V
# wch-link is not supported yet in official openOCD yet. We need to either use
# 1. download openocd as part of mounriver studio http://www.mounriver.com/download or
# 2. compiled from modified source https://github.com/kprasadvnsi/riscv-openocd-wch
#
-# Note: For Linux, somehow openocd in mounriver studio does not seem to have wch-link enable,
+# Note: For Linux, somehow openocd in mounriver studio does not seem to have wch-link enable,
# therefore we need to compile it from source as follows:
# git clone https://github.com/kprasadvnsi/riscv-openocd-wch
# cd riscv-openocd-wch
diff --git a/hw/bsp/ch32v307/system_ch32v30x.c b/hw/bsp/ch32v307/system_ch32v30x.c
index 12b18d7b8..23f783df4 100644
--- a/hw/bsp/ch32v307/system_ch32v30x.c
+++ b/hw/bsp/ch32v307/system_ch32v30x.c
@@ -8,17 +8,17 @@
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* SPDX-License-Identifier: Apache-2.0
*********************************************************************************/
-#include "ch32v30x.h"
+#include "ch32v30x.h"
-/*
-* Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
+/*
+* Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
* reset the HSI is used as SYSCLK source).
-* If none of the define below is enabled, the HSI is used as System clock source.
+* If none of the define below is enabled, the HSI is used as System clock source.
*/
// #define SYSCLK_FREQ_HSE HSE_VALUE
-/* #define SYSCLK_FREQ_24MHz 24000000 */
+/* #define SYSCLK_FREQ_24MHz 24000000 */
//#define SYSCLK_FREQ_48MHz 48000000
-/* #define SYSCLK_FREQ_56MHz 56000000 */
+/* #define SYSCLK_FREQ_56MHz 56000000 */
//#define SYSCLK_FREQ_72MHz 72000000
//#define SYSCLK_FREQ_96MHz 96000000
//#define SYSCLK_FREQ_120MHz 120000000
@@ -60,7 +60,7 @@ static void SetSysClock(void);
#elif defined SYSCLK_FREQ_48MHz
static void SetSysClockTo48(void);
#elif defined SYSCLK_FREQ_56MHz
- static void SetSysClockTo56(void);
+ static void SetSysClockTo56(void);
#elif defined SYSCLK_FREQ_72MHz
static void SetSysClockTo72(void);
@@ -90,7 +90,7 @@ void SystemInit (void)
RCC->CFGR0 &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR0 &= (uint32_t)0xF0FF0000;
-#endif
+#endif
RCC->CTLR &= (uint32_t)0xFEF6FFFF;
RCC->CTLR &= (uint32_t)0xFFFBFFFF;
@@ -101,8 +101,8 @@ void SystemInit (void)
RCC->INTR = 0x00FF0000;
RCC->CFGR2 = 0x00000000;
#else
- RCC->INTR = 0x009F0000;
-#endif
+ RCC->INTR = 0x009F0000;
+#endif
SetSysClock();
}
@@ -118,18 +118,18 @@ void SystemCoreClockUpdate (void)
uint32_t tmp = 0, pllmull = 0, pllsource = 0, Pll_6_5 = 0;
tmp = RCC->CFGR0 & RCC_SWS;
-
+
switch (tmp)
{
case 0x00:
SystemCoreClock = HSI_VALUE;
break;
- case 0x04:
+ case 0x04:
SystemCoreClock = HSE_VALUE;
break;
- case 0x08:
+ case 0x08:
pllmull = RCC->CFGR0 & RCC_PLLMULL;
- pllsource = RCC->CFGR0 & RCC_PLLSRC;
+ pllsource = RCC->CFGR0 & RCC_PLLSRC;
pllmull = ( pllmull >> 18) + 2;
#ifdef CH32V30x_D8
@@ -149,7 +149,7 @@ void SystemCoreClockUpdate (void)
SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
}
else
- {
+ {
if ((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET)
{
SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
@@ -167,9 +167,9 @@ void SystemCoreClockUpdate (void)
SystemCoreClock = HSI_VALUE;
break;
}
-
+
tmp = AHBPrescTable[((RCC->CFGR0 & RCC_HPRE) >> 4)];
- SystemCoreClock >>= tmp;
+ SystemCoreClock >>= tmp;
}
/*********************************************************************
@@ -188,7 +188,7 @@ static void SetSysClock(void)
#elif defined SYSCLK_FREQ_48MHz
SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
- SetSysClockTo56();
+ SetSysClockTo56();
#elif defined SYSCLK_FREQ_72MHz
SetSysClockTo72();
#elif defined SYSCLK_FREQ_96MHz
@@ -199,9 +199,9 @@ static void SetSysClock(void)
SetSysClockTo144();
#endif
-
+
/* If none of the define above is enabled, the HSI is used as System clock
- * source (default after reset)
+ * source (default after reset)
*/
}
@@ -218,14 +218,14 @@ static void SetSysClock(void)
static void SetSysClockToHSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
-
+
RCC->CTLR |= ((uint32_t)RCC_HSEON);
-
+
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
- StartUpCounter++;
+ StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
@@ -235,20 +235,20 @@ static void SetSysClockToHSE(void)
else
{
HSEStatus = (uint32_t)0x00;
- }
+ }
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
- RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1;
-
+
/* Select HSE as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
- RCC->CFGR0 |= (uint32_t)RCC_SW_HSE;
+ RCC->CFGR0 |= (uint32_t)RCC_SW_HSE;
/* Wait till HSE is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x04)
@@ -256,11 +256,11 @@ static void SetSysClockToHSE(void)
}
}
else
- {
+ {
/* If HSE fails to start-up, the application will have wrong clock
- * configuration. User can add here some code to deal with this error
+ * configuration. User can add here some code to deal with this error
*/
- }
+ }
}
#elif defined SYSCLK_FREQ_24MHz
@@ -275,14 +275,14 @@ static void SetSysClockToHSE(void)
static void SetSysClockTo24(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
-
+
RCC->CTLR |= ((uint32_t)RCC_HSEON);
-
+
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
- StartUpCounter++;
+ StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
@@ -292,13 +292,13 @@ static void SetSysClockTo24(void)
else
{
HSEStatus = (uint32_t)0x00;
- }
+ }
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
- RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
- RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1;
@@ -318,18 +318,18 @@ static void SetSysClockTo24(void)
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
- RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
- {
+ {
/* If HSE fails to start-up, the application will have wrong clock
- * configuration. User can add here some code to deal with this error
+ * configuration. User can add here some code to deal with this error
*/
- }
+ }
}
#elif defined SYSCLK_FREQ_48MHz
@@ -344,14 +344,14 @@ static void SetSysClockTo24(void)
static void SetSysClockTo48(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
-
-
+
+
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
- StartUpCounter++;
+ StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
@@ -361,14 +361,14 @@ static void SetSysClockTo48(void)
else
{
HSEStatus = (uint32_t)0x00;
- }
+ }
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
- RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
- RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
@@ -389,19 +389,19 @@ static void SetSysClockTo48(void)
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
- RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
- {
+ {
/*
* If HSE fails to start-up, the application will have wrong clock
- * configuration. User can add here some code to deal with this error
+ * configuration. User can add here some code to deal with this error
*/
- }
+ }
}
#elif defined SYSCLK_FREQ_56MHz
@@ -416,14 +416,14 @@ static void SetSysClockTo48(void)
static void SetSysClockTo56(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
-
+
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
- StartUpCounter++;
+ StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
@@ -433,17 +433,17 @@ static void SetSysClockTo56(void)
else
{
HSEStatus = (uint32_t)0x00;
- }
+ }
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
- RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
-
+
/* PLL configuration: PLLCLK = HSE * 7 = 56 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
@@ -462,19 +462,19 @@ static void SetSysClockTo56(void)
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
- RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
- {
+ {
/*
* If HSE fails to start-up, the application will have wrong clock
- * configuration. User can add here some code to deal with this error
+ * configuration. User can add here some code to deal with this error
*/
- }
+ }
}
#elif defined SYSCLK_FREQ_72MHz
@@ -489,14 +489,14 @@ static void SetSysClockTo56(void)
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
-
+
RCC->CTLR |= ((uint32_t)RCC_HSEON);
-
+
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
- StartUpCounter++;
+ StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
@@ -506,17 +506,17 @@ static void SetSysClockTo72(void)
else
{
HSEStatus = (uint32_t)0x00;
- }
+ }
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
- RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
- RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
-
+
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
@@ -532,20 +532,20 @@ static void SetSysClockTo72(void)
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
- }
+ }
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
- RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
- {
+ {
/*
* If HSE fails to start-up, the application will have wrong clock
- * configuration. User can add here some code to deal with this error
+ * configuration. User can add here some code to deal with this error
*/
}
}
diff --git a/hw/bsp/ch32v307/system_ch32v30x.h b/hw/bsp/ch32v307/system_ch32v30x.h
index 0e0ef4e51..ad81058c7 100644
--- a/hw/bsp/ch32v307/system_ch32v30x.h
+++ b/hw/bsp/ch32v307/system_ch32v30x.h
@@ -7,16 +7,16 @@
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* SPDX-License-Identifier: Apache-2.0
*******************************************************************************/
-#ifndef __SYSTEM_CH32V30x_H
+#ifndef __SYSTEM_CH32V30x_H
#define __SYSTEM_CH32V30x_H
#ifdef __cplusplus
extern "C" {
-#endif
+#endif
extern uint32_t SystemCoreClock; /* System Clock Frequency (Core Clock) */
-/* System_Exported_Functions */
+/* System_Exported_Functions */
extern void SystemInit(void);
extern void SystemCoreClockUpdate(void);
@@ -25,6 +25,3 @@ extern void SystemCoreClockUpdate(void);
#endif
#endif /*__CH32V30x_SYSTEM_H */
-
-
-
diff --git a/hw/bsp/d5035_01/board.mk b/hw/bsp/d5035_01/board.mk
deleted file mode 100644
index b7796b9d8..000000000
--- a/hw/bsp/d5035_01/board.mk
+++ /dev/null
@@ -1,61 +0,0 @@
-DEPS_SUBMODULES += hw/mcu/microchip
-HWREV ?= 1
-
-CFLAGS += \
- -mthumb \
- -mabi=aapcs \
- -mlong-calls \
- -mcpu=cortex-m4 \
- -mfloat-abi=hard \
- -mfpu=fpv4-sp-d16 \
- -nostdlib -nostartfiles \
- -D__SAME51J19A__ \
- -DCONF_CPU_FREQUENCY=80000000 \
- -DCONF_GCLK_USB_FREQUENCY=48000000 \
- -DCFG_TUSB_MCU=OPT_MCU_SAME5X \
- -DD5035_01=1 \
- -DBOARD_NAME="\"D5035-01\"" \
- -DSVC_Handler=SVCall_Handler \
- -DHWREV=$(HWREV)
-
-# suppress warning caused by vendor mcu driver
-CFLAGS += -Wno-error=cast-qual
-
-# All source paths should be relative to the top level.
-LD_FILE = hw/bsp/$(BOARD)/same51j19a_flash.ld
-
-SRC_C += \
- src/portable/microchip/samd/dcd_samd.c \
- hw/mcu/microchip/same51/gcc/gcc/startup_same51.c \
- hw/mcu/microchip/same51/gcc/system_same51.c
-
-ifdef SYSCALLS
-ifneq ($(SYSCALLS),0)
- SRC_C += hw/mcu/microchip/same51/hal/utils/src/utils_syscalls.c
-endif
-endif
-
-ifdef LOG
-ifneq ($(LOG),0)
- SRC_C += hw/mcu/microchip/same51/hal/utils/src/utils_syscalls.c
-endif
-endif
-
-INC += \
- $(TOP)/hw/mcu/microchip/same51/ \
- $(TOP)/hw/mcu/microchip/same51/config \
- $(TOP)/hw/mcu/microchip/same51/include \
- $(TOP)/hw/mcu/microchip/same51/hal/include \
- $(TOP)/hw/mcu/microchip/same51/hal/utils/include \
- $(TOP)/hw/mcu/microchip/same51/hpl/port \
- $(TOP)/hw/mcu/microchip/same51/hri \
- $(TOP)/hw/mcu/microchip/same51/CMSIS/Include
-
-# For freeRTOS port source
-FREERTOS_PORT = ARM_CM4F
-
-# For flash-jlink target
-JLINK_DEVICE = ATSAME51J19
-
-# flash using jlink
-flash: flash-jlink
diff --git a/hw/bsp/da14695_dk_usb/board.mk b/hw/bsp/da14695_dk_usb/board.mk
index e969c79c2..980b1a361 100644
--- a/hw/bsp/da14695_dk_usb/board.mk
+++ b/hw/bsp/da14695_dk_usb/board.mk
@@ -1,3 +1,5 @@
+MCU_FAMILY_DIR = hw/mcu/dialog/da1469x
+
CFLAGS += \
-flto \
-mthumb \
@@ -11,7 +13,7 @@ CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_DA1469X \
-DCFG_TUD_ENDPOINT0_SIZE=8\
-MCU_FAMILY_DIR = hw/mcu/dialog/da1469x
+LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
# All source paths should be relative to the top level.
LD_FILE = hw/bsp/$(BOARD)/da1469x.ld
@@ -31,7 +33,7 @@ INC += \
$(TOP)/$(MCU_FAMILY_DIR)/SDK_10.0.8.105/sdk/bsp/include
# For freeRTOS port source
-FREERTOS_PORT = ARM_CM33_NTZ/non_secure
+FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM33_NTZ/non_secure
# For flash-jlink target
JLINK_DEVICE = DA14695
@@ -52,4 +54,3 @@ flash-dialog: $(BUILD)/$(PROJECT).bin
@echo go >> $(BUILD)/$(BOARD).jlink
@echo exit >> $(BUILD)/$(BOARD).jlink
$(JLINKEXE) -device $(JLINK_DEVICE) -if $(JLINK_IF) -JTAGConf -1,-1 -speed auto -CommandFile $(BUILD)/$(BOARD).jlink
-
diff --git a/hw/bsp/da14695_dk_usb/da14695_dk_usb.c b/hw/bsp/da14695_dk_usb/da14695_dk_usb.c
index a4d996810..667b83de3 100644
--- a/hw/bsp/da14695_dk_usb/da14695_dk_usb.c
+++ b/hw/bsp/da14695_dk_usb/da14695_dk_usb.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jerzy Kasenberg
@@ -24,7 +24,7 @@
* This file is part of the TinyUSB stack.
*/
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include
#include
diff --git a/hw/bsp/da14695_dk_usb/da1469x.ld b/hw/bsp/da14695_dk_usb/da1469x.ld
index 96507d6e7..8cc1d9d99 100644
--- a/hw/bsp/da14695_dk_usb/da1469x.ld
+++ b/hw/bsp/da14695_dk_usb/da1469x.ld
@@ -242,4 +242,3 @@ SECTIONS
/* Check that intvect is at the beginning of RAM */
ASSERT(__intvect_start__ == ORIGIN(RAM), "intvect is not at beginning of RAM")
}
-
diff --git a/hw/bsp/da1469x_dk_pro/board.mk b/hw/bsp/da1469x_dk_pro/board.mk
index 980fc422f..5282f93a3 100644
--- a/hw/bsp/da1469x_dk_pro/board.mk
+++ b/hw/bsp/da1469x_dk_pro/board.mk
@@ -1,3 +1,5 @@
+MCU_FAMILY_DIR = hw/mcu/dialog/da1469x
+
CFLAGS += \
-flto \
-mthumb \
@@ -11,7 +13,7 @@ CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_DA1469X \
-DCFG_TUD_ENDPOINT0_SIZE=8\
-MCU_FAMILY_DIR = hw/mcu/dialog/da1469x
+LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
# All source paths should be relative to the top level.
LD_FILE = hw/bsp/$(BOARD)/da1469x.ld
@@ -31,7 +33,7 @@ INC += \
$(TOP)/$(MCU_FAMILY_DIR)/SDK_10.0.8.105/sdk/bsp/include
# For freeRTOS port source
-FREERTOS_PORT = ARM_CM33_NTZ/non_secure
+FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM33_NTZ/non_secure
# For flash-jlink target
JLINK_DEVICE = DA14699
@@ -52,4 +54,3 @@ flash-dialog: $(BUILD)/$(PROJECT).bin
@echo go >> $(BUILD)/$(BOARD).jlink
@echo exit >> $(BUILD)/$(BOARD).jlink
$(JLINKEXE) -device $(JLINK_DEVICE) -if $(JLINK_IF) -JTAGConf -1,-1 -speed auto -CommandFile $(BUILD)/$(BOARD).jlink
-
diff --git a/hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c b/hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c
index 13113fb95..21bd62714 100644
--- a/hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c
+++ b/hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jerzy Kasenberg
@@ -24,7 +24,7 @@
* This file is part of the TinyUSB stack.
*/
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include
#include
diff --git a/hw/bsp/da1469x_dk_pro/da1469x.ld b/hw/bsp/da1469x_dk_pro/da1469x.ld
index 96507d6e7..8cc1d9d99 100644
--- a/hw/bsp/da1469x_dk_pro/da1469x.ld
+++ b/hw/bsp/da1469x_dk_pro/da1469x.ld
@@ -242,4 +242,3 @@ SECTIONS
/* Check that intvect is at the beginning of RAM */
ASSERT(__intvect_start__ == ORIGIN(RAM), "intvect is not at beginning of RAM")
}
-
diff --git a/hw/bsp/ea4357/board.mk b/hw/bsp/ea4357/board.mk
deleted file mode 100644
index 6f243c6a2..000000000
--- a/hw/bsp/ea4357/board.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-DEPS_SUBMODULES += hw/mcu/nxp/lpcopen
-
-CFLAGS += \
- -flto \
- -mthumb \
- -mabi=aapcs \
- -mcpu=cortex-m4 \
- -mfloat-abi=hard \
- -mfpu=fpv4-sp-d16 \
- -nostdlib \
- -DCORE_M4 \
- -D__USE_LPCOPEN \
- -DCFG_TUSB_MCU=OPT_MCU_LPC43XX
-
-# mcu driver cause following warnings
-CFLAGS += -Wno-error=unused-parameter -Wno-error=strict-prototypes -Wno-error=cast-qual
-
-MCU_DIR = hw/mcu/nxp/lpcopen/lpc43xx/lpc_chip_43xx
-
-# All source paths should be relative to the top level.
-LD_FILE = hw/bsp/$(BOARD)/lpc4357.ld
-
-SRC_C += \
- src/portable/chipidea/ci_hs/dcd_ci_hs.c \
- src/portable/chipidea/ci_hs/hcd_ci_hs.c \
- src/portable/ehci/ehci.c \
- $(MCU_DIR)/../gcc/cr_startup_lpc43xx.c \
- $(MCU_DIR)/src/chip_18xx_43xx.c \
- $(MCU_DIR)/src/clock_18xx_43xx.c \
- $(MCU_DIR)/src/gpio_18xx_43xx.c \
- $(MCU_DIR)/src/sysinit_18xx_43xx.c \
- $(MCU_DIR)/src/i2c_18xx_43xx.c \
- $(MCU_DIR)/src/i2cm_18xx_43xx.c \
- $(MCU_DIR)/src/uart_18xx_43xx.c \
- $(MCU_DIR)/src/fpu_init.c
-
-INC += \
- $(TOP)/$(MCU_DIR)/inc \
- $(TOP)/$(MCU_DIR)/inc/config_43xx
-
-# For freeRTOS port source
-FREERTOS_PORT = ARM_CM4F
-
-# For flash-jlink target
-JLINK_DEVICE = LPC4357_M4
-
-# flash using jlink
-flash: flash-jlink
diff --git a/hw/bsp/esp32s2/boards/CMakeLists.txt b/hw/bsp/esp32s2/boards/CMakeLists.txt
deleted file mode 100644
index c3c687a70..000000000
--- a/hw/bsp/esp32s2/boards/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-idf_component_register(SRCS esp32s2.c
- INCLUDE_DIRS "." "${BOARD}"
- PRIV_REQUIRES "driver"
- REQUIRES freertos src led_strip)
-
-# Apply board specific content
-include("${BOARD}/board.cmake")
-
-target_include_directories(${COMPONENT_TARGET} PUBLIC
- "${TOP}/hw"
- "${TOP}/src"
-)
diff --git a/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.cmake b/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.cmake
deleted file mode 100644
index d33962676..000000000
--- a/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.cmake
+++ /dev/null
@@ -1,17 +0,0 @@
-# Apply board specific content here
-target_include_directories(${COMPONENT_LIB} PRIVATE .)
-
-idf_build_get_property(idf_target IDF_TARGET)
-
-message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}")
-
-if(NOT ${idf_target} STREQUAL "esp32s2")
- message(FATAL_ERROR "Incorrect target for board ${BOARD}: $ENV{IDF_TARGET}(${idf_target}), try to clean the build first." )
-endif()
-
-set(IDF_TARGET "esp32s2" FORCE)
-
-target_compile_options(${COMPONENT_TARGET} PUBLIC
- "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2"
- "-DCFG_TUSB_OS=OPT_OS_FREERTOS"
-)
\ No newline at end of file
diff --git a/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.cmake b/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.cmake
deleted file mode 100644
index d33962676..000000000
--- a/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.cmake
+++ /dev/null
@@ -1,17 +0,0 @@
-# Apply board specific content here
-target_include_directories(${COMPONENT_LIB} PRIVATE .)
-
-idf_build_get_property(idf_target IDF_TARGET)
-
-message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}")
-
-if(NOT ${idf_target} STREQUAL "esp32s2")
- message(FATAL_ERROR "Incorrect target for board ${BOARD}: $ENV{IDF_TARGET}(${idf_target}), try to clean the build first." )
-endif()
-
-set(IDF_TARGET "esp32s2" FORCE)
-
-target_compile_options(${COMPONENT_TARGET} PUBLIC
- "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2"
- "-DCFG_TUSB_OS=OPT_OS_FREERTOS"
-)
\ No newline at end of file
diff --git a/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.cmake b/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.cmake
deleted file mode 100644
index d5c17b9be..000000000
--- a/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.cmake
+++ /dev/null
@@ -1,17 +0,0 @@
-# Apply board specific content here
-target_include_directories(${COMPONENT_LIB} PRIVATE .)
-
-idf_build_get_property(idf_target IDF_TARGET)
-
-message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}")
-
-if(NOT ${idf_target} STREQUAL "esp32s2")
- message(FATAL_ERROR "Incorrect target for board ${BOARD}: (${idf_target}), try to clean the build first." )
-endif()
-
-set(IDF_TARGET "esp32s2" FORCE)
-
-target_compile_options(${COMPONENT_TARGET} PUBLIC
- "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2"
- "-DCFG_TUSB_OS=OPT_OS_FREERTOS"
-)
\ No newline at end of file
diff --git a/hw/bsp/esp32s2/boards/esp32s2.c b/hw/bsp/esp32s2/boards/esp32s2.c
deleted file mode 100644
index a7ca82deb..000000000
--- a/hw/bsp/esp32s2/boards/esp32s2.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2020, 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.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "../../board.h"
-#include "board.h"
-
-#include "esp_rom_gpio.h"
-#include "hal/gpio_ll.h"
-#include "hal/usb_hal.h"
-#include "soc/usb_periph.h"
-
-#include "driver/rmt.h"
-
-#if ESP_IDF_VERSION_MAJOR > 4
- #include "esp_private/periph_ctrl.h"
-#else
- #include "driver/periph_ctrl.h"
-#endif
-
-#ifdef NEOPIXEL_PIN
-#include "led_strip.h"
-static led_strip_t *strip;
-#endif
-
-//--------------------------------------------------------------------+
-// MACRO TYPEDEF CONSTANT ENUM DECLARATION
-//--------------------------------------------------------------------+
-
-static void configure_pins(usb_hal_context_t *usb);
-
-// Initialize on-board peripherals : led, button, uart and USB
-void board_init(void)
-{
-
-#ifdef NEOPIXEL_PIN
- #ifdef NEOPIXEL_POWER_PIN
- gpio_reset_pin(NEOPIXEL_POWER_PIN);
- gpio_set_direction(NEOPIXEL_POWER_PIN, GPIO_MODE_OUTPUT);
- gpio_set_level(NEOPIXEL_POWER_PIN, NEOPIXEL_POWER_STATE);
- #endif
-
- // WS2812 Neopixel driver with RMT peripheral
- rmt_config_t config = RMT_DEFAULT_CONFIG_TX(NEOPIXEL_PIN, RMT_CHANNEL_0);
- config.clk_div = 2; // set counter clock to 40MHz
-
- rmt_config(&config);
- rmt_driver_install(config.channel, 0, 0);
-
- led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(1, (led_strip_dev_t) config.channel);
- strip = led_strip_new_rmt_ws2812(&strip_config);
- strip->clear(strip, 100); // off led
-#endif
-
- // Button
- esp_rom_gpio_pad_select_gpio(BUTTON_PIN);
- gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT);
- gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY);
-
- // USB Controller Hal init
- periph_module_reset(PERIPH_USB_MODULE);
- periph_module_enable(PERIPH_USB_MODULE);
-
- usb_hal_context_t hal = {
- .use_external_phy = false // use built-in PHY
- };
- usb_hal_init(&hal);
- configure_pins(&hal);
-}
-
-static void configure_pins(usb_hal_context_t *usb)
-{
- /* usb_periph_iopins currently configures USB_OTG as USB Device.
- * Introduce additional parameters in usb_hal_context_t when adding support
- * for USB Host.
- */
- for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) {
- if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) {
- esp_rom_gpio_pad_select_gpio(iopin->pin);
- if (iopin->is_output) {
- esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false);
- } else {
- esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false);
-#if ESP_IDF_VERSION_MAJOR > 4
- if ((iopin->pin != GPIO_MATRIX_CONST_ZERO_INPUT) && (iopin->pin != GPIO_MATRIX_CONST_ONE_INPUT))
-#else
- if ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH))
-#endif
- {
- gpio_ll_input_enable(&GPIO, iopin->pin);
- }
- }
- esp_rom_gpio_pad_unhold(iopin->pin);
- }
- }
- if (!usb->use_external_phy) {
- gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3);
- gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3);
- }
-}
-
-// Turn LED on or off
-void board_led_write(bool state)
-{
-#ifdef NEOPIXEL_PIN
- strip->set_pixel(strip, 0, (state ? 0x88 : 0x00), 0x00, 0x00);
- strip->refresh(strip, 100);
-#endif
-}
-
-// Get the current state of button
-// a '1' means active (pressed), a '0' means inactive.
-uint32_t board_button_read(void)
-{
- return gpio_get_level(BUTTON_PIN) == BUTTON_STATE_ACTIVE;
-}
-
-// Get characters from UART
-int board_uart_read(uint8_t* buf, int len)
-{
- (void) buf; (void) len;
- return 0;
-}
-
-// Send characters to UART
-int board_uart_write(void const * buf, int len)
-{
- (void) buf; (void) len;
- return 0;
-}
-
diff --git a/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.cmake b/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.cmake
deleted file mode 100644
index d5c17b9be..000000000
--- a/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.cmake
+++ /dev/null
@@ -1,17 +0,0 @@
-# Apply board specific content here
-target_include_directories(${COMPONENT_LIB} PRIVATE .)
-
-idf_build_get_property(idf_target IDF_TARGET)
-
-message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}")
-
-if(NOT ${idf_target} STREQUAL "esp32s2")
- message(FATAL_ERROR "Incorrect target for board ${BOARD}: (${idf_target}), try to clean the build first." )
-endif()
-
-set(IDF_TARGET "esp32s2" FORCE)
-
-target_compile_options(${COMPONENT_TARGET} PUBLIC
- "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2"
- "-DCFG_TUSB_OS=OPT_OS_FREERTOS"
-)
\ No newline at end of file
diff --git a/hw/bsp/esp32s2/boards/espressif_saola_1/board.cmake b/hw/bsp/esp32s2/boards/espressif_saola_1/board.cmake
deleted file mode 100644
index d5c17b9be..000000000
--- a/hw/bsp/esp32s2/boards/espressif_saola_1/board.cmake
+++ /dev/null
@@ -1,17 +0,0 @@
-# Apply board specific content here
-target_include_directories(${COMPONENT_LIB} PRIVATE .)
-
-idf_build_get_property(idf_target IDF_TARGET)
-
-message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}")
-
-if(NOT ${idf_target} STREQUAL "esp32s2")
- message(FATAL_ERROR "Incorrect target for board ${BOARD}: (${idf_target}), try to clean the build first." )
-endif()
-
-set(IDF_TARGET "esp32s2" FORCE)
-
-target_compile_options(${COMPONENT_TARGET} PUBLIC
- "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2"
- "-DCFG_TUSB_OS=OPT_OS_FREERTOS"
-)
\ No newline at end of file
diff --git a/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt b/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt
deleted file mode 100644
index 6d0fcbc86..000000000
--- a/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-set(component_srcs "src/led_strip_rmt_ws2812.c")
-
-idf_component_register(SRCS "${component_srcs}"
- INCLUDE_DIRS "include"
- PRIV_INCLUDE_DIRS ""
- PRIV_REQUIRES "driver"
- REQUIRES "")
-
diff --git a/hw/bsp/esp32s2/components/led_strip/include/led_strip.h b/hw/bsp/esp32s2/components/led_strip/include/led_strip.h
deleted file mode 100644
index a9dffc325..000000000
--- a/hw/bsp/esp32s2/components/led_strip/include/led_strip.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "esp_err.h"
-
-/**
-* @brief LED Strip Type
-*
-*/
-typedef struct led_strip_s led_strip_t;
-
-/**
-* @brief LED Strip Device Type
-*
-*/
-typedef void *led_strip_dev_t;
-
-/**
-* @brief Declare of LED Strip Type
-*
-*/
-struct led_strip_s {
- /**
- * @brief Set RGB for a specific pixel
- *
- * @param strip: LED strip
- * @param index: index of pixel to set
- * @param red: red part of color
- * @param green: green part of color
- * @param blue: blue part of color
- *
- * @return
- * - ESP_OK: Set RGB for a specific pixel successfully
- * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters
- * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred
- */
- esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue);
-
- /**
- * @brief Refresh memory colors to LEDs
- *
- * @param strip: LED strip
- * @param timeout_ms: timeout value for refreshing task
- *
- * @return
- * - ESP_OK: Refresh successfully
- * - ESP_ERR_TIMEOUT: Refresh failed because of timeout
- * - ESP_FAIL: Refresh failed because some other error occurred
- *
- * @note:
- * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip.
- */
- esp_err_t (*refresh)(led_strip_t *strip, uint32_t timeout_ms);
-
- /**
- * @brief Clear LED strip (turn off all LEDs)
- *
- * @param strip: LED strip
- * @param timeout_ms: timeout value for clearing task
- *
- * @return
- * - ESP_OK: Clear LEDs successfully
- * - ESP_ERR_TIMEOUT: Clear LEDs failed because of timeout
- * - ESP_FAIL: Clear LEDs failed because some other error occurred
- */
- esp_err_t (*clear)(led_strip_t *strip, uint32_t timeout_ms);
-
- /**
- * @brief Free LED strip resources
- *
- * @param strip: LED strip
- *
- * @return
- * - ESP_OK: Free resources successfully
- * - ESP_FAIL: Free resources failed because error occurred
- */
- esp_err_t (*del)(led_strip_t *strip);
-};
-
-/**
-* @brief LED Strip Configuration Type
-*
-*/
-typedef struct {
- uint32_t max_leds; /*!< Maximum LEDs in a single strip */
- led_strip_dev_t dev; /*!< LED strip device (e.g. RMT channel, PWM channel, etc) */
-} led_strip_config_t;
-
-/**
- * @brief Default configuration for LED strip
- *
- */
-#define LED_STRIP_DEFAULT_CONFIG(number, dev_hdl) \
- { \
- .max_leds = number, \
- .dev = dev_hdl, \
- }
-
-/**
-* @brief Install a new ws2812 driver (based on RMT peripheral)
-*
-* @param config: LED strip configuration
-* @return
-* LED strip instance or NULL
-*/
-led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c b/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c
deleted file mode 100644
index fd1746cad..000000000
--- a/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#include
-#include
-#include
-#include "esp_log.h"
-#include "esp_attr.h"
-#include "led_strip.h"
-#include "driver/rmt.h"
-
-static const char *TAG = "ws2812";
-#define STRIP_CHECK(a, str, goto_tag, ret_value, ...) \
- do \
- { \
- if (!(a)) \
- { \
- ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
- ret = ret_value; \
- goto goto_tag; \
- } \
- } while (0)
-
-#define WS2812_T0H_NS (350)
-#define WS2812_T0L_NS (1000)
-#define WS2812_T1H_NS (1000)
-#define WS2812_T1L_NS (350)
-#define WS2812_RESET_US (280)
-
-static uint32_t ws2812_t0h_ticks = 0;
-static uint32_t ws2812_t1h_ticks = 0;
-static uint32_t ws2812_t0l_ticks = 0;
-static uint32_t ws2812_t1l_ticks = 0;
-
-typedef struct {
- led_strip_t parent;
- rmt_channel_t rmt_channel;
- uint32_t strip_len;
- uint8_t buffer[0];
-} ws2812_t;
-
-/**
- * @brief Convert RGB data to RMT format.
- *
- * @note For WS2812, R,G,B each contains 256 different choices (i.e. uint8_t)
- *
- * @param[in] src: source data, to converted to RMT format
- * @param[in] dest: place where to store the convert result
- * @param[in] src_size: size of source data
- * @param[in] wanted_num: number of RMT items that want to get
- * @param[out] translated_size: number of source data that got converted
- * @param[out] item_num: number of RMT items which are converted from source data
- */
-static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size,
- size_t wanted_num, size_t *translated_size, size_t *item_num)
-{
- if (src == NULL || dest == NULL) {
- *translated_size = 0;
- *item_num = 0;
- return;
- }
- const rmt_item32_t bit0 = {{{ ws2812_t0h_ticks, 1, ws2812_t0l_ticks, 0 }}}; //Logical 0
- const rmt_item32_t bit1 = {{{ ws2812_t1h_ticks, 1, ws2812_t1l_ticks, 0 }}}; //Logical 1
- size_t size = 0;
- size_t num = 0;
- uint8_t *psrc = (uint8_t *)src;
- rmt_item32_t *pdest = dest;
- while (size < src_size && num < wanted_num) {
- for (int i = 0; i < 8; i++) {
- // MSB first
- if (*psrc & (1 << (7 - i))) {
- pdest->val = bit1.val;
- } else {
- pdest->val = bit0.val;
- }
- num++;
- pdest++;
- }
- size++;
- psrc++;
- }
- *translated_size = size;
- *item_num = num;
-}
-
-static esp_err_t ws2812_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue)
-{
- esp_err_t ret = ESP_OK;
- ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent);
- STRIP_CHECK(index < ws2812->strip_len, "index out of the maximum number of leds", err, ESP_ERR_INVALID_ARG);
- uint32_t start = index * 3;
- // In thr order of GRB
- ws2812->buffer[start + 0] = green & 0xFF;
- ws2812->buffer[start + 1] = red & 0xFF;
- ws2812->buffer[start + 2] = blue & 0xFF;
- return ESP_OK;
-err:
- return ret;
-}
-
-static esp_err_t ws2812_refresh(led_strip_t *strip, uint32_t timeout_ms)
-{
- esp_err_t ret = ESP_OK;
- ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent);
- STRIP_CHECK(rmt_write_sample(ws2812->rmt_channel, ws2812->buffer, ws2812->strip_len * 3, true) == ESP_OK,
- "transmit RMT samples failed", err, ESP_FAIL);
- return rmt_wait_tx_done(ws2812->rmt_channel, pdMS_TO_TICKS(timeout_ms));
-err:
- return ret;
-}
-
-static esp_err_t ws2812_clear(led_strip_t *strip, uint32_t timeout_ms)
-{
- ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent);
- // Write zero to turn off all leds
- memset(ws2812->buffer, 0, ws2812->strip_len * 3);
- return ws2812_refresh(strip, timeout_ms);
-}
-
-static esp_err_t ws2812_del(led_strip_t *strip)
-{
- ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent);
- free(ws2812);
- return ESP_OK;
-}
-
-led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config)
-{
- led_strip_t *ret = NULL;
- STRIP_CHECK(config, "configuration can't be null", err, NULL);
-
- // 24 bits per led
- uint32_t ws2812_size = sizeof(ws2812_t) + config->max_leds * 3;
- ws2812_t *ws2812 = calloc(1, ws2812_size);
- STRIP_CHECK(ws2812, "request memory for ws2812 failed", err, NULL);
-
- uint32_t counter_clk_hz = 0;
- STRIP_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev, &counter_clk_hz) == ESP_OK,
- "get rmt counter clock failed", err, NULL);
- // ns -> ticks
- float ratio = (float)counter_clk_hz / 1e9;
- ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS);
- ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS);
- ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS);
- ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS);
-
- // set ws2812 to rmt adapter
- rmt_translator_init((rmt_channel_t)config->dev, ws2812_rmt_adapter);
-
- ws2812->rmt_channel = (rmt_channel_t)config->dev;
- ws2812->strip_len = config->max_leds;
-
- ws2812->parent.set_pixel = ws2812_set_pixel;
- ws2812->parent.refresh = ws2812_refresh;
- ws2812->parent.clear = ws2812_clear;
- ws2812->parent.del = ws2812_del;
-
- return &ws2812->parent;
-err:
- return ret;
-}
diff --git a/hw/bsp/esp32s2/family.cmake b/hw/bsp/esp32s2/family.cmake
deleted file mode 100644
index f3d41d041..000000000
--- a/hw/bsp/esp32s2/family.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-cmake_minimum_required(VERSION 3.5)
-
-# Add example src and bsp directories
-set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s2/boards" "${TOP}/hw/bsp/esp32s2/components")
-include($ENV{IDF_PATH}/tools/cmake/project.cmake)
-set(SUPPORTED_TARGETS esp32s2)
-set(FAMILY_MCUS ESP32S2)
diff --git a/hw/bsp/esp32s3/boards/CMakeLists.txt b/hw/bsp/esp32s3/boards/CMakeLists.txt
deleted file mode 100644
index e1b921ae9..000000000
--- a/hw/bsp/esp32s3/boards/CMakeLists.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-idf_component_register(SRCS esp32s3.c
- INCLUDE_DIRS "." "${BOARD}"
- PRIV_REQUIRES "driver"
- REQUIRES freertos src led_strip)
-
-# Apply board specific content
-include("${BOARD}/board.cmake")
-
-idf_component_get_property( FREERTOS_ORIG_INCLUDE_PATH freertos ORIG_INCLUDE_PATH)
-target_include_directories(${COMPONENT_TARGET} PUBLIC
- "${FREERTOS_ORIG_INCLUDE_PATH}"
- "${TOP}/hw"
- "${TOP}/src"
-)
diff --git a/hw/bsp/esp32s3/boards/esp32s3.c b/hw/bsp/esp32s3/boards/esp32s3.c
deleted file mode 100644
index a7ca82deb..000000000
--- a/hw/bsp/esp32s3/boards/esp32s3.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2020, 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.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "../../board.h"
-#include "board.h"
-
-#include "esp_rom_gpio.h"
-#include "hal/gpio_ll.h"
-#include "hal/usb_hal.h"
-#include "soc/usb_periph.h"
-
-#include "driver/rmt.h"
-
-#if ESP_IDF_VERSION_MAJOR > 4
- #include "esp_private/periph_ctrl.h"
-#else
- #include "driver/periph_ctrl.h"
-#endif
-
-#ifdef NEOPIXEL_PIN
-#include "led_strip.h"
-static led_strip_t *strip;
-#endif
-
-//--------------------------------------------------------------------+
-// MACRO TYPEDEF CONSTANT ENUM DECLARATION
-//--------------------------------------------------------------------+
-
-static void configure_pins(usb_hal_context_t *usb);
-
-// Initialize on-board peripherals : led, button, uart and USB
-void board_init(void)
-{
-
-#ifdef NEOPIXEL_PIN
- #ifdef NEOPIXEL_POWER_PIN
- gpio_reset_pin(NEOPIXEL_POWER_PIN);
- gpio_set_direction(NEOPIXEL_POWER_PIN, GPIO_MODE_OUTPUT);
- gpio_set_level(NEOPIXEL_POWER_PIN, NEOPIXEL_POWER_STATE);
- #endif
-
- // WS2812 Neopixel driver with RMT peripheral
- rmt_config_t config = RMT_DEFAULT_CONFIG_TX(NEOPIXEL_PIN, RMT_CHANNEL_0);
- config.clk_div = 2; // set counter clock to 40MHz
-
- rmt_config(&config);
- rmt_driver_install(config.channel, 0, 0);
-
- led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(1, (led_strip_dev_t) config.channel);
- strip = led_strip_new_rmt_ws2812(&strip_config);
- strip->clear(strip, 100); // off led
-#endif
-
- // Button
- esp_rom_gpio_pad_select_gpio(BUTTON_PIN);
- gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT);
- gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY);
-
- // USB Controller Hal init
- periph_module_reset(PERIPH_USB_MODULE);
- periph_module_enable(PERIPH_USB_MODULE);
-
- usb_hal_context_t hal = {
- .use_external_phy = false // use built-in PHY
- };
- usb_hal_init(&hal);
- configure_pins(&hal);
-}
-
-static void configure_pins(usb_hal_context_t *usb)
-{
- /* usb_periph_iopins currently configures USB_OTG as USB Device.
- * Introduce additional parameters in usb_hal_context_t when adding support
- * for USB Host.
- */
- for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) {
- if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) {
- esp_rom_gpio_pad_select_gpio(iopin->pin);
- if (iopin->is_output) {
- esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false);
- } else {
- esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false);
-#if ESP_IDF_VERSION_MAJOR > 4
- if ((iopin->pin != GPIO_MATRIX_CONST_ZERO_INPUT) && (iopin->pin != GPIO_MATRIX_CONST_ONE_INPUT))
-#else
- if ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH))
-#endif
- {
- gpio_ll_input_enable(&GPIO, iopin->pin);
- }
- }
- esp_rom_gpio_pad_unhold(iopin->pin);
- }
- }
- if (!usb->use_external_phy) {
- gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3);
- gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3);
- }
-}
-
-// Turn LED on or off
-void board_led_write(bool state)
-{
-#ifdef NEOPIXEL_PIN
- strip->set_pixel(strip, 0, (state ? 0x88 : 0x00), 0x00, 0x00);
- strip->refresh(strip, 100);
-#endif
-}
-
-// Get the current state of button
-// a '1' means active (pressed), a '0' means inactive.
-uint32_t board_button_read(void)
-{
- return gpio_get_level(BUTTON_PIN) == BUTTON_STATE_ACTIVE;
-}
-
-// Get characters from UART
-int board_uart_read(uint8_t* buf, int len)
-{
- (void) buf; (void) len;
- return 0;
-}
-
-// Send characters to UART
-int board_uart_write(void const * buf, int len)
-{
- (void) buf; (void) len;
- return 0;
-}
-
diff --git a/hw/bsp/esp32s3/boards/espressif_addax_1/board.cmake b/hw/bsp/esp32s3/boards/espressif_addax_1/board.cmake
deleted file mode 100644
index 8996ff9dc..000000000
--- a/hw/bsp/esp32s3/boards/espressif_addax_1/board.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-# Apply board specific content here
-target_include_directories(${COMPONENT_LIB} PRIVATE .)
-
-target_compile_options(${COMPONENT_TARGET} PUBLIC
- "-DCFG_TUSB_MCU=OPT_MCU_ESP32S3"
- "-DCFG_TUSB_OS=OPT_OS_FREERTOS"
-)
\ No newline at end of file
diff --git a/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.cmake b/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.cmake
deleted file mode 100644
index 8996ff9dc..000000000
--- a/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-# Apply board specific content here
-target_include_directories(${COMPONENT_LIB} PRIVATE .)
-
-target_compile_options(${COMPONENT_TARGET} PUBLIC
- "-DCFG_TUSB_MCU=OPT_MCU_ESP32S3"
- "-DCFG_TUSB_OS=OPT_OS_FREERTOS"
-)
\ No newline at end of file
diff --git a/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.cmake b/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.cmake
deleted file mode 100644
index 8996ff9dc..000000000
--- a/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-# Apply board specific content here
-target_include_directories(${COMPONENT_LIB} PRIVATE .)
-
-target_compile_options(${COMPONENT_TARGET} PUBLIC
- "-DCFG_TUSB_MCU=OPT_MCU_ESP32S3"
- "-DCFG_TUSB_OS=OPT_OS_FREERTOS"
-)
\ No newline at end of file
diff --git a/hw/bsp/esp32s3/components/led_strip/CMakeLists.txt b/hw/bsp/esp32s3/components/led_strip/CMakeLists.txt
deleted file mode 100644
index 6d0fcbc86..000000000
--- a/hw/bsp/esp32s3/components/led_strip/CMakeLists.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-set(component_srcs "src/led_strip_rmt_ws2812.c")
-
-idf_component_register(SRCS "${component_srcs}"
- INCLUDE_DIRS "include"
- PRIV_INCLUDE_DIRS ""
- PRIV_REQUIRES "driver"
- REQUIRES "")
-
diff --git a/hw/bsp/esp32s3/components/led_strip/include/led_strip.h b/hw/bsp/esp32s3/components/led_strip/include/led_strip.h
deleted file mode 100644
index a9dffc325..000000000
--- a/hw/bsp/esp32s3/components/led_strip/include/led_strip.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "esp_err.h"
-
-/**
-* @brief LED Strip Type
-*
-*/
-typedef struct led_strip_s led_strip_t;
-
-/**
-* @brief LED Strip Device Type
-*
-*/
-typedef void *led_strip_dev_t;
-
-/**
-* @brief Declare of LED Strip Type
-*
-*/
-struct led_strip_s {
- /**
- * @brief Set RGB for a specific pixel
- *
- * @param strip: LED strip
- * @param index: index of pixel to set
- * @param red: red part of color
- * @param green: green part of color
- * @param blue: blue part of color
- *
- * @return
- * - ESP_OK: Set RGB for a specific pixel successfully
- * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters
- * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred
- */
- esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue);
-
- /**
- * @brief Refresh memory colors to LEDs
- *
- * @param strip: LED strip
- * @param timeout_ms: timeout value for refreshing task
- *
- * @return
- * - ESP_OK: Refresh successfully
- * - ESP_ERR_TIMEOUT: Refresh failed because of timeout
- * - ESP_FAIL: Refresh failed because some other error occurred
- *
- * @note:
- * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip.
- */
- esp_err_t (*refresh)(led_strip_t *strip, uint32_t timeout_ms);
-
- /**
- * @brief Clear LED strip (turn off all LEDs)
- *
- * @param strip: LED strip
- * @param timeout_ms: timeout value for clearing task
- *
- * @return
- * - ESP_OK: Clear LEDs successfully
- * - ESP_ERR_TIMEOUT: Clear LEDs failed because of timeout
- * - ESP_FAIL: Clear LEDs failed because some other error occurred
- */
- esp_err_t (*clear)(led_strip_t *strip, uint32_t timeout_ms);
-
- /**
- * @brief Free LED strip resources
- *
- * @param strip: LED strip
- *
- * @return
- * - ESP_OK: Free resources successfully
- * - ESP_FAIL: Free resources failed because error occurred
- */
- esp_err_t (*del)(led_strip_t *strip);
-};
-
-/**
-* @brief LED Strip Configuration Type
-*
-*/
-typedef struct {
- uint32_t max_leds; /*!< Maximum LEDs in a single strip */
- led_strip_dev_t dev; /*!< LED strip device (e.g. RMT channel, PWM channel, etc) */
-} led_strip_config_t;
-
-/**
- * @brief Default configuration for LED strip
- *
- */
-#define LED_STRIP_DEFAULT_CONFIG(number, dev_hdl) \
- { \
- .max_leds = number, \
- .dev = dev_hdl, \
- }
-
-/**
-* @brief Install a new ws2812 driver (based on RMT peripheral)
-*
-* @param config: LED strip configuration
-* @return
-* LED strip instance or NULL
-*/
-led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c b/hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c
deleted file mode 100644
index fd1746cad..000000000
--- a/hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#include
-#include
-#include
-#include "esp_log.h"
-#include "esp_attr.h"
-#include "led_strip.h"
-#include "driver/rmt.h"
-
-static const char *TAG = "ws2812";
-#define STRIP_CHECK(a, str, goto_tag, ret_value, ...) \
- do \
- { \
- if (!(a)) \
- { \
- ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
- ret = ret_value; \
- goto goto_tag; \
- } \
- } while (0)
-
-#define WS2812_T0H_NS (350)
-#define WS2812_T0L_NS (1000)
-#define WS2812_T1H_NS (1000)
-#define WS2812_T1L_NS (350)
-#define WS2812_RESET_US (280)
-
-static uint32_t ws2812_t0h_ticks = 0;
-static uint32_t ws2812_t1h_ticks = 0;
-static uint32_t ws2812_t0l_ticks = 0;
-static uint32_t ws2812_t1l_ticks = 0;
-
-typedef struct {
- led_strip_t parent;
- rmt_channel_t rmt_channel;
- uint32_t strip_len;
- uint8_t buffer[0];
-} ws2812_t;
-
-/**
- * @brief Convert RGB data to RMT format.
- *
- * @note For WS2812, R,G,B each contains 256 different choices (i.e. uint8_t)
- *
- * @param[in] src: source data, to converted to RMT format
- * @param[in] dest: place where to store the convert result
- * @param[in] src_size: size of source data
- * @param[in] wanted_num: number of RMT items that want to get
- * @param[out] translated_size: number of source data that got converted
- * @param[out] item_num: number of RMT items which are converted from source data
- */
-static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size,
- size_t wanted_num, size_t *translated_size, size_t *item_num)
-{
- if (src == NULL || dest == NULL) {
- *translated_size = 0;
- *item_num = 0;
- return;
- }
- const rmt_item32_t bit0 = {{{ ws2812_t0h_ticks, 1, ws2812_t0l_ticks, 0 }}}; //Logical 0
- const rmt_item32_t bit1 = {{{ ws2812_t1h_ticks, 1, ws2812_t1l_ticks, 0 }}}; //Logical 1
- size_t size = 0;
- size_t num = 0;
- uint8_t *psrc = (uint8_t *)src;
- rmt_item32_t *pdest = dest;
- while (size < src_size && num < wanted_num) {
- for (int i = 0; i < 8; i++) {
- // MSB first
- if (*psrc & (1 << (7 - i))) {
- pdest->val = bit1.val;
- } else {
- pdest->val = bit0.val;
- }
- num++;
- pdest++;
- }
- size++;
- psrc++;
- }
- *translated_size = size;
- *item_num = num;
-}
-
-static esp_err_t ws2812_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue)
-{
- esp_err_t ret = ESP_OK;
- ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent);
- STRIP_CHECK(index < ws2812->strip_len, "index out of the maximum number of leds", err, ESP_ERR_INVALID_ARG);
- uint32_t start = index * 3;
- // In thr order of GRB
- ws2812->buffer[start + 0] = green & 0xFF;
- ws2812->buffer[start + 1] = red & 0xFF;
- ws2812->buffer[start + 2] = blue & 0xFF;
- return ESP_OK;
-err:
- return ret;
-}
-
-static esp_err_t ws2812_refresh(led_strip_t *strip, uint32_t timeout_ms)
-{
- esp_err_t ret = ESP_OK;
- ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent);
- STRIP_CHECK(rmt_write_sample(ws2812->rmt_channel, ws2812->buffer, ws2812->strip_len * 3, true) == ESP_OK,
- "transmit RMT samples failed", err, ESP_FAIL);
- return rmt_wait_tx_done(ws2812->rmt_channel, pdMS_TO_TICKS(timeout_ms));
-err:
- return ret;
-}
-
-static esp_err_t ws2812_clear(led_strip_t *strip, uint32_t timeout_ms)
-{
- ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent);
- // Write zero to turn off all leds
- memset(ws2812->buffer, 0, ws2812->strip_len * 3);
- return ws2812_refresh(strip, timeout_ms);
-}
-
-static esp_err_t ws2812_del(led_strip_t *strip)
-{
- ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent);
- free(ws2812);
- return ESP_OK;
-}
-
-led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config)
-{
- led_strip_t *ret = NULL;
- STRIP_CHECK(config, "configuration can't be null", err, NULL);
-
- // 24 bits per led
- uint32_t ws2812_size = sizeof(ws2812_t) + config->max_leds * 3;
- ws2812_t *ws2812 = calloc(1, ws2812_size);
- STRIP_CHECK(ws2812, "request memory for ws2812 failed", err, NULL);
-
- uint32_t counter_clk_hz = 0;
- STRIP_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev, &counter_clk_hz) == ESP_OK,
- "get rmt counter clock failed", err, NULL);
- // ns -> ticks
- float ratio = (float)counter_clk_hz / 1e9;
- ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS);
- ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS);
- ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS);
- ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS);
-
- // set ws2812 to rmt adapter
- rmt_translator_init((rmt_channel_t)config->dev, ws2812_rmt_adapter);
-
- ws2812->rmt_channel = (rmt_channel_t)config->dev;
- ws2812->strip_len = config->max_leds;
-
- ws2812->parent.set_pixel = ws2812_set_pixel;
- ws2812->parent.refresh = ws2812_refresh;
- ws2812->parent.clear = ws2812_clear;
- ws2812->parent.del = ws2812_del;
-
- return &ws2812->parent;
-err:
- return ret;
-}
diff --git a/hw/bsp/esp32s3/family.cmake b/hw/bsp/esp32s3/family.cmake
deleted file mode 100644
index 511dd58bb..000000000
--- a/hw/bsp/esp32s3/family.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-cmake_minimum_required(VERSION 3.5)
-
-# Add example src and bsp directories
-set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s3/boards" "${TOP}/hw/bsp/esp32s3/components")
-include($ENV{IDF_PATH}/tools/cmake/project.cmake)
-set(SUPPORTED_TARGETS esp32s3)
-set(FAMILY_MCUS ESP32S3)
diff --git a/hw/bsp/esp32s3/family.mk b/hw/bsp/esp32s3/family.mk
deleted file mode 100644
index cf153ffc2..000000000
--- a/hw/bsp/esp32s3/family.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-#DEPS_SUBMODULES +=
-
-.PHONY: all clean flash bootloader-flash app-flash erase monitor dfu-flash dfu
-
-all:
- idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) -DIDF_TARGET=esp32s3 build
-
-build: all
-
-clean:
- idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) clean
-
-fullclean:
- if test -f sdkconfig; then $(RM) -f sdkconfig ; fi
- if test -d $(BUILD); then $(RM) -rf $(BUILD) ; fi
-
-flash bootloader-flash app-flash erase monitor dfu-flash dfu:
- idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@
-
-uf2: $(BUILD)/$(PROJECT).uf2
-
-UF2_FAMILY_ID = 0xc47e5767
-$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).bin
- @echo CREATE $@
- $(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -b 0x0 -c -o $@ $^
-
diff --git a/hw/bsp/espressif/boards/CMakeLists.txt b/hw/bsp/espressif/boards/CMakeLists.txt
new file mode 100644
index 000000000..8209e8747
--- /dev/null
+++ b/hw/bsp/espressif/boards/CMakeLists.txt
@@ -0,0 +1,8 @@
+set(hw_dir "${CMAKE_CURRENT_LIST_DIR}/../../../")
+
+idf_component_register(SRCS family.c
+ INCLUDE_DIRS "." ${BOARD} ${hw_dir}
+ PRIV_REQUIRES "driver"
+ REQUIRES led_strip src tinyusb_src)
+
+target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=format)
diff --git a/hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.cmake b/hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.cmake
new file mode 100644
index 000000000..18c956714
--- /dev/null
+++ b/hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.cmake
@@ -0,0 +1,2 @@
+# Apply board specific content here
+set(IDF_TARGET "esp32")
diff --git a/hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.h b/hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.h
new file mode 100644
index 000000000..0c53df06b
--- /dev/null
+++ b/hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.h
@@ -0,0 +1,53 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020, 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.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef BOARD_H_
+#define BOARD_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define NEOPIXEL_PIN 0
+#define NEOPIXEL_POWER_PIN 2
+#define NEOPIXEL_POWER_STATE 1
+
+#define BUTTON_PIN 38
+#define BUTTON_STATE_ACTIVE 0
+
+// SPI for USB host shield
+#define MAX3421_SPI_HOST SPI3_HOST
+#define MAX3421_SCK_PIN 5
+#define MAX3421_MOSI_PIN 19
+#define MAX3421_MISO_PIN 21
+#define MAX3421_CS_PIN 33
+#define MAX3421_INTR_PIN 15
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* BOARD_H_ */
diff --git a/hw/bsp/espressif/boards/adafruit_feather_esp32s2/board.cmake b/hw/bsp/espressif/boards/adafruit_feather_esp32s2/board.cmake
new file mode 100644
index 000000000..abbdf7abc
--- /dev/null
+++ b/hw/bsp/espressif/boards/adafruit_feather_esp32s2/board.cmake
@@ -0,0 +1,2 @@
+# Apply board specific content here
+set(IDF_TARGET "esp32s2")
diff --git a/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h b/hw/bsp/espressif/boards/adafruit_feather_esp32s2/board.h
similarity index 87%
rename from hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h
rename to hw/bsp/espressif/boards/adafruit_feather_esp32s2/board.h
index 43e00901d..9aa2e7535 100644
--- a/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h
+++ b/hw/bsp/espressif/boards/adafruit_feather_esp32s2/board.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
@@ -38,6 +38,14 @@
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
+// SPI for USB host shield
+#define MAX3421_SPI_HOST SPI2_HOST
+#define MAX3421_SCK_PIN 36
+#define MAX3421_MOSI_PIN 35
+#define MAX3421_MISO_PIN 37
+#define MAX3421_CS_PIN 10
+#define MAX3421_INTR_PIN 9
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/bsp/espressif/boards/adafruit_magtag_29gray/board.cmake b/hw/bsp/espressif/boards/adafruit_magtag_29gray/board.cmake
new file mode 100644
index 000000000..abbdf7abc
--- /dev/null
+++ b/hw/bsp/espressif/boards/adafruit_magtag_29gray/board.cmake
@@ -0,0 +1,2 @@
+# Apply board specific content here
+set(IDF_TARGET "esp32s2")
diff --git a/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h b/hw/bsp/espressif/boards/adafruit_magtag_29gray/board.h
similarity index 99%
rename from hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h
rename to hw/bsp/espressif/boards/adafruit_magtag_29gray/board.h
index 16e30b685..084a7aaf2 100644
--- a/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h
+++ b/hw/bsp/espressif/boards/adafruit_magtag_29gray/board.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
diff --git a/hw/bsp/espressif/boards/adafruit_metro_esp32s2/board.cmake b/hw/bsp/espressif/boards/adafruit_metro_esp32s2/board.cmake
new file mode 100644
index 000000000..abbdf7abc
--- /dev/null
+++ b/hw/bsp/espressif/boards/adafruit_metro_esp32s2/board.cmake
@@ -0,0 +1,2 @@
+# Apply board specific content here
+set(IDF_TARGET "esp32s2")
diff --git a/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h b/hw/bsp/espressif/boards/adafruit_metro_esp32s2/board.h
similarity index 87%
rename from hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h
rename to hw/bsp/espressif/boards/adafruit_metro_esp32s2/board.h
index 49a2474bc..137ea71ae 100644
--- a/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h
+++ b/hw/bsp/espressif/boards/adafruit_metro_esp32s2/board.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
@@ -36,6 +36,14 @@
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
+// SPI for USB host shield
+#define MAX3421_SPI_HOST SPI2_HOST
+#define MAX3421_SCK_PIN 36
+#define MAX3421_MOSI_PIN 35
+#define MAX3421_MISO_PIN 37
+#define MAX3421_CS_PIN 15
+#define MAX3421_INTR_PIN 14
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/bsp/espressif/boards/espressif_addax_1/board.cmake b/hw/bsp/espressif/boards/espressif_addax_1/board.cmake
new file mode 100644
index 000000000..9bac46d64
--- /dev/null
+++ b/hw/bsp/espressif/boards/espressif_addax_1/board.cmake
@@ -0,0 +1,2 @@
+# Apply board specific content here
+set(IDF_TARGET "esp32s3")
diff --git a/hw/bsp/esp32s3/boards/espressif_addax_1/board.h b/hw/bsp/espressif/boards/espressif_addax_1/board.h
similarity index 99%
rename from hw/bsp/esp32s3/boards/espressif_addax_1/board.h
rename to hw/bsp/espressif/boards/espressif_addax_1/board.h
index fff24ba44..d4690f732 100644
--- a/hw/bsp/esp32s3/boards/espressif_addax_1/board.h
+++ b/hw/bsp/espressif/boards/espressif_addax_1/board.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
diff --git a/hw/bsp/espressif/boards/espressif_c3_devkitc/board.cmake b/hw/bsp/espressif/boards/espressif_c3_devkitc/board.cmake
new file mode 100644
index 000000000..ab4bc1a06
--- /dev/null
+++ b/hw/bsp/espressif/boards/espressif_c3_devkitc/board.cmake
@@ -0,0 +1,2 @@
+# Apply board specific content here
+set(IDF_TARGET "esp32c3")
diff --git a/hw/bsp/espressif/boards/espressif_c3_devkitc/board.h b/hw/bsp/espressif/boards/espressif_c3_devkitc/board.h
new file mode 100644
index 000000000..243dd47f6
--- /dev/null
+++ b/hw/bsp/espressif/boards/espressif_c3_devkitc/board.h
@@ -0,0 +1,51 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020, 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.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef BOARD_H_
+#define BOARD_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define NEOPIXEL_PIN 8
+
+#define BUTTON_PIN 9
+#define BUTTON_STATE_ACTIVE 0
+
+// SPI for USB host shield
+#define MAX3421_SPI_HOST SPI2_HOST
+#define MAX3421_SCK_PIN 4
+#define MAX3421_MOSI_PIN 6
+#define MAX3421_MISO_PIN 5
+#define MAX3421_CS_PIN 10
+#define MAX3421_INTR_PIN 7
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* BOARD_H_ */
diff --git a/hw/bsp/espressif/boards/espressif_kaluga_1/board.cmake b/hw/bsp/espressif/boards/espressif_kaluga_1/board.cmake
new file mode 100644
index 000000000..abbdf7abc
--- /dev/null
+++ b/hw/bsp/espressif/boards/espressif_kaluga_1/board.cmake
@@ -0,0 +1,2 @@
+# Apply board specific content here
+set(IDF_TARGET "esp32s2")
diff --git a/hw/bsp/espressif/boards/espressif_kaluga_1/board.h b/hw/bsp/espressif/boards/espressif_kaluga_1/board.h
new file mode 100644
index 000000000..613e6ae0c
--- /dev/null
+++ b/hw/bsp/espressif/boards/espressif_kaluga_1/board.h
@@ -0,0 +1,52 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020, 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.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef BOARD_H_
+#define BOARD_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// Note: need to insert jumper next to WS2812 pixel
+#define NEOPIXEL_PIN 45
+
+#define BUTTON_PIN 0
+#define BUTTON_STATE_ACTIVE 0
+
+// SPI for USB host shield
+#define MAX3421_SPI_HOST SPI2_HOST
+#define MAX3421_SCK_PIN 36
+#define MAX3421_MOSI_PIN 35
+#define MAX3421_MISO_PIN 37
+#define MAX3421_CS_PIN 15
+#define MAX3421_INTR_PIN 14
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* BOARD_H_ */
diff --git a/hw/bsp/espressif/boards/espressif_s2_devkitc/board.cmake b/hw/bsp/espressif/boards/espressif_s2_devkitc/board.cmake
new file mode 100644
index 000000000..abbdf7abc
--- /dev/null
+++ b/hw/bsp/espressif/boards/espressif_s2_devkitc/board.cmake
@@ -0,0 +1,2 @@
+# Apply board specific content here
+set(IDF_TARGET "esp32s2")
diff --git a/hw/bsp/esp32s2/boards/espressif_saola_1/board.h b/hw/bsp/espressif/boards/espressif_s2_devkitc/board.h
similarity index 99%
rename from hw/bsp/esp32s2/boards/espressif_saola_1/board.h
rename to hw/bsp/espressif/boards/espressif_s2_devkitc/board.h
index f450b9a8b..e068efef9 100644
--- a/hw/bsp/esp32s2/boards/espressif_saola_1/board.h
+++ b/hw/bsp/espressif/boards/espressif_s2_devkitc/board.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
diff --git a/hw/bsp/espressif/boards/espressif_s3_devkitc/board.cmake b/hw/bsp/espressif/boards/espressif_s3_devkitc/board.cmake
new file mode 100644
index 000000000..9bac46d64
--- /dev/null
+++ b/hw/bsp/espressif/boards/espressif_s3_devkitc/board.cmake
@@ -0,0 +1,2 @@
+# Apply board specific content here
+set(IDF_TARGET "esp32s3")
diff --git a/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.h b/hw/bsp/espressif/boards/espressif_s3_devkitc/board.h
similarity index 87%
rename from hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.h
rename to hw/bsp/espressif/boards/espressif_s3_devkitc/board.h
index c7940c56e..a319fbc61 100644
--- a/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.h
+++ b/hw/bsp/espressif/boards/espressif_s3_devkitc/board.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
@@ -36,6 +36,14 @@
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
+// SPI for USB host shield
+#define MAX3421_SPI_HOST SPI2_HOST
+#define MAX3421_SCK_PIN 39
+#define MAX3421_MOSI_PIN 42
+#define MAX3421_MISO_PIN 21
+#define MAX3421_CS_PIN 15
+#define MAX3421_INTR_PIN 14
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/bsp/espressif/boards/espressif_s3_devkitm/board.cmake b/hw/bsp/espressif/boards/espressif_s3_devkitm/board.cmake
new file mode 100644
index 000000000..9bac46d64
--- /dev/null
+++ b/hw/bsp/espressif/boards/espressif_s3_devkitm/board.cmake
@@ -0,0 +1,2 @@
+# Apply board specific content here
+set(IDF_TARGET "esp32s3")
diff --git a/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.h b/hw/bsp/espressif/boards/espressif_s3_devkitm/board.h
similarity index 87%
rename from hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.h
rename to hw/bsp/espressif/boards/espressif_s3_devkitm/board.h
index c7940c56e..a319fbc61 100644
--- a/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.h
+++ b/hw/bsp/espressif/boards/espressif_s3_devkitm/board.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
@@ -36,6 +36,14 @@
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
+// SPI for USB host shield
+#define MAX3421_SPI_HOST SPI2_HOST
+#define MAX3421_SCK_PIN 39
+#define MAX3421_MOSI_PIN 42
+#define MAX3421_MISO_PIN 21
+#define MAX3421_CS_PIN 15
+#define MAX3421_INTR_PIN 14
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/bsp/espressif/boards/espressif_saola_1/board.cmake b/hw/bsp/espressif/boards/espressif_saola_1/board.cmake
new file mode 100644
index 000000000..abbdf7abc
--- /dev/null
+++ b/hw/bsp/espressif/boards/espressif_saola_1/board.cmake
@@ -0,0 +1,2 @@
+# Apply board specific content here
+set(IDF_TARGET "esp32s2")
diff --git a/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h b/hw/bsp/espressif/boards/espressif_saola_1/board.h
similarity index 88%
rename from hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h
rename to hw/bsp/espressif/boards/espressif_saola_1/board.h
index 6bb44f76d..e068efef9 100644
--- a/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h
+++ b/hw/bsp/espressif/boards/espressif_saola_1/board.h
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
@@ -31,8 +31,9 @@
extern "C" {
#endif
-// Note: need to insert jumper next to WS2812 pixel
-#define NEOPIXEL_PIN 45
+// Note: On the production version (v1.2) WS2812 is connected to GPIO 18,
+// however earlier revision v1.1 WS2812 is connected to GPIO 17
+#define NEOPIXEL_PIN 18
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c
new file mode 100644
index 000000000..02e478a0c
--- /dev/null
+++ b/hw/bsp/espressif/boards/family.c
@@ -0,0 +1,309 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020, 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.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "bsp/board_api.h"
+#include "board.h"
+
+#include "esp_rom_gpio.h"
+#include "esp_mac.h"
+#include "hal/gpio_ll.h"
+
+#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
+#include "hal/usb_hal.h"
+#include "soc/usb_periph.h"
+static void configure_pins(usb_hal_context_t* usb);
+#endif
+
+#include "driver/gpio.h"
+#include "driver/uart.h"
+
+#if ESP_IDF_VERSION_MAJOR > 4
+ #include "esp_private/periph_ctrl.h"
+#else
+ #include "driver/periph_ctrl.h"
+#endif
+
+// Note; current code use UART0 can cause device to reset while monitoring
+#define USE_UART 0
+#define UART_ID UART_NUM_0
+
+#ifdef NEOPIXEL_PIN
+#include "led_strip.h"
+static led_strip_handle_t led_strip;
+#endif
+
+#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
+#include "driver/spi_master.h"
+static void max3421_init(void);
+#endif
+
+
+//--------------------------------------------------------------------+
+// Implementation
+//--------------------------------------------------------------------+
+
+// Initialize on-board peripherals : led, button, uart and USB
+void board_init(void) {
+#if USE_UART
+ // uart init
+ uart_config_t uart_config = {
+ .baud_rate = 115200,
+ .data_bits = UART_DATA_8_BITS,
+ .parity = UART_PARITY_DISABLE,
+ .stop_bits = UART_STOP_BITS_1,
+ .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
+ };
+ uart_driver_install(UART_ID, 1024, 0, 0, NULL, 0);
+ uart_param_config(UART_ID, &uart_config);
+#endif
+
+#ifdef NEOPIXEL_PIN
+ #ifdef NEOPIXEL_POWER_PIN
+ gpio_reset_pin(NEOPIXEL_POWER_PIN);
+ gpio_set_direction(NEOPIXEL_POWER_PIN, GPIO_MODE_OUTPUT);
+ gpio_set_level(NEOPIXEL_POWER_PIN, NEOPIXEL_POWER_STATE);
+ #endif
+
+ // WS2812 Neopixel driver with RMT peripheral
+ led_strip_rmt_config_t rmt_config = {
+ .clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
+ .resolution_hz = 10 * 1000 * 1000, // RMT counter clock frequency, default = 10 Mhz
+ .flags.with_dma = false, // DMA feature is available on ESP target like ESP32-S3
+ };
+
+ led_strip_config_t strip_config = {
+ .strip_gpio_num = NEOPIXEL_PIN, // The GPIO that connected to the LED strip's data line
+ .max_leds = 1, // The number of LEDs in the strip,
+ .led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip
+ .led_model = LED_MODEL_WS2812, // LED strip model
+ .flags.invert_out = false, // whether to invert the output signal
+ };
+
+ ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
+ led_strip_clear(led_strip); // off
+#endif
+
+ // Button
+ esp_rom_gpio_pad_select_gpio(BUTTON_PIN);
+ gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT);
+ gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY);
+
+#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
+ // USB Controller Hal init
+ periph_module_reset(PERIPH_USB_MODULE);
+ periph_module_enable(PERIPH_USB_MODULE);
+
+ usb_hal_context_t hal = {
+ .use_external_phy = false // use built-in PHY
+ };
+ usb_hal_init(&hal);
+ configure_pins(&hal);
+#endif
+
+#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
+ max3421_init();
+#endif
+}
+
+#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
+static void configure_pins(usb_hal_context_t* usb) {
+ /* usb_periph_iopins currently configures USB_OTG as USB Device.
+ * Introduce additional parameters in usb_hal_context_t when adding support
+ * for USB Host. */
+ for (const usb_iopin_dsc_t* iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) {
+ if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) {
+ esp_rom_gpio_pad_select_gpio(iopin->pin);
+ if (iopin->is_output) {
+ esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false);
+ } else {
+ esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false);
+#if ESP_IDF_VERSION_MAJOR > 4
+ if ((iopin->pin != GPIO_MATRIX_CONST_ZERO_INPUT) && (iopin->pin != GPIO_MATRIX_CONST_ONE_INPUT))
+#else
+ if ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH))
+#endif
+ {
+ gpio_ll_input_enable(&GPIO, iopin->pin);
+ }
+ }
+ esp_rom_gpio_pad_unhold(iopin->pin);
+ }
+ }
+
+ if (!usb->use_external_phy) {
+ gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3);
+ gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3);
+ }
+}
+#endif
+
+//--------------------------------------------------------------------+
+// Board porting API
+//--------------------------------------------------------------------+
+
+size_t board_get_unique_id(uint8_t id[], size_t max_len) {
+ // use factory default MAC as serial ID
+ esp_efuse_mac_get_default(id);
+ return 6;
+}
+
+void board_led_write(bool state) {
+#ifdef NEOPIXEL_PIN
+ led_strip_set_pixel(led_strip, 0, state ? 0x08 : 0x00, 0x00, 0x00);
+ led_strip_refresh(led_strip);
+#endif
+}
+
+// Get the current state of button
+// a '1' means active (pressed), a '0' means inactive.
+uint32_t board_button_read(void) {
+ return gpio_get_level(BUTTON_PIN) == BUTTON_STATE_ACTIVE;
+}
+
+// Get characters from UART
+int board_uart_read(uint8_t* buf, int len) {
+#if USE_UART
+ return uart_read_bytes(UART_ID, buf, len, 0);
+#else
+ return -1;
+#endif
+}
+
+// Send characters to UART
+int board_uart_write(void const* buf, int len) {
+ (void) buf;
+ (void) len;
+ return 0;
+}
+
+int board_getchar(void) {
+ uint8_t c = 0;
+ return board_uart_read(&c, 1) > 0 ? (int) c : (-1);
+}
+
+//--------------------------------------------------------------------+
+// API: SPI transfer with MAX3421E, must be implemented by application
+//--------------------------------------------------------------------+
+#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
+
+static spi_device_handle_t max3421_spi;
+SemaphoreHandle_t max3421_intr_sem;
+
+static void IRAM_ATTR max3421_isr_handler(void* arg) {
+ (void) arg; // arg is gpio num
+
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ xSemaphoreGiveFromISR(max3421_intr_sem, &xHigherPriorityTaskWoken);
+ if (xHigherPriorityTaskWoken) {
+ portYIELD_FROM_ISR();
+ }
+}
+
+static void max3421_intr_task(void* param) {
+ (void) param;
+
+ while (1) {
+ xSemaphoreTake(max3421_intr_sem, portMAX_DELAY);
+ tuh_int_handler(BOARD_TUH_RHPORT, false);
+ }
+}
+
+static void max3421_init(void) {
+ // CS pin
+ gpio_set_direction(MAX3421_CS_PIN, GPIO_MODE_OUTPUT);
+ gpio_set_level(MAX3421_CS_PIN, 1);
+
+ // SPI
+ spi_bus_config_t buscfg = {
+ .miso_io_num = MAX3421_MISO_PIN,
+ .mosi_io_num = MAX3421_MOSI_PIN,
+ .sclk_io_num = MAX3421_SCK_PIN,
+ .quadwp_io_num = -1,
+ .quadhd_io_num = -1,
+ .data4_io_num = -1,
+ .data5_io_num = -1,
+ .data6_io_num = -1,
+ .data7_io_num = -1,
+ .max_transfer_sz = 1024
+ };
+ ESP_ERROR_CHECK(spi_bus_initialize(MAX3421_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
+
+ spi_device_interface_config_t max3421_cfg = {
+ .mode = 0,
+ .clock_speed_hz = 20000000, // S2/S3 can work with 26 Mhz, but esp32 seems only work up to 20 Mhz
+ .spics_io_num = -1, // manual control CS
+ .queue_size = 1
+ };
+ ESP_ERROR_CHECK(spi_bus_add_device(MAX3421_SPI_HOST, &max3421_cfg, &max3421_spi));
+
+ // Interrupt pin
+ max3421_intr_sem = xSemaphoreCreateBinary();
+ xTaskCreate(max3421_intr_task, "max3421 intr", 2048, NULL, configMAX_PRIORITIES - 2, NULL);
+
+ gpio_set_direction(MAX3421_INTR_PIN, GPIO_MODE_INPUT);
+ gpio_set_intr_type(MAX3421_INTR_PIN, GPIO_INTR_NEGEDGE);
+
+ gpio_install_isr_service(0);
+ gpio_isr_handler_add(MAX3421_INTR_PIN, max3421_isr_handler, NULL);
+}
+
+void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
+ (void) rhport;
+ if (enabled) {
+ gpio_intr_enable(MAX3421_INTR_PIN);
+ } else {
+ gpio_intr_disable(MAX3421_INTR_PIN);
+ }
+}
+
+void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) {
+ (void) rhport;
+ gpio_set_level(MAX3421_CS_PIN, active ? 0 : 1);
+}
+
+bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) {
+ (void) rhport;
+
+ if (tx_buf == NULL) {
+ // fifo read, transmit rx_buf as dummy
+ tx_buf = rx_buf;
+ }
+
+ // length in bits
+ size_t const len_bits = xfer_bytes << 3;
+
+ spi_transaction_t xact = {
+ .length = len_bits,
+ .rxlength = rx_buf ? len_bits : 0,
+ .tx_buffer = tx_buf,
+ .rx_buffer = rx_buf
+ };
+
+ ESP_ERROR_CHECK(spi_device_transmit(max3421_spi, &xact));
+ return true;
+}
+
+#endif
diff --git a/hw/bsp/espressif/components/led_strip/CHANGELOG.md b/hw/bsp/espressif/components/led_strip/CHANGELOG.md
new file mode 100644
index 000000000..51c0cd30c
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/CHANGELOG.md
@@ -0,0 +1,38 @@
+## 2.5.0
+
+- Enabled support for IDF4.4 and above
+ - with RMT backend only
+- Added API `led_strip_set_pixel_hsv`
+
+## 2.4.0
+
+- Support configurable SPI mode to control leds
+ - recommend enabling DMA when using SPI mode
+
+## 2.3.0
+
+- Support configurable RMT channel size by setting `mem_block_symbols`
+
+## 2.2.0
+
+- Support for 4 components RGBW leds (SK6812):
+ - in led_strip_config_t new fields
+ led_pixel_format, controlling byte format (LED_PIXEL_FORMAT_GRB, LED_PIXEL_FORMAT_GRBW)
+ led_model, used to configure bit timing (LED_MODEL_WS2812, LED_MODEL_SK6812)
+ - new API led_strip_set_pixel_rgbw
+ - new interface type set_pixel_rgbw
+
+## 2.1.0
+
+- Support DMA feature, which offloads the CPU by a lot when it comes to drive a bunch of LEDs
+- Support various RMT clock sources
+- Acquire and release the power management lock before and after each refresh
+- New driver flag: `invert_out` which can invert the led control signal by hardware
+
+## 2.0.0
+
+- Reimplemented the driver using the new RMT driver (`driver/rmt_tx.h`)
+
+## 1.0.0
+
+- Initial driver version, based on the legacy RMT driver (`driver/rmt.h`)
diff --git a/hw/bsp/espressif/components/led_strip/CMakeLists.txt b/hw/bsp/espressif/components/led_strip/CMakeLists.txt
new file mode 100644
index 000000000..15de610cc
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/CMakeLists.txt
@@ -0,0 +1,22 @@
+include($ENV{IDF_PATH}/tools/cmake/version.cmake)
+
+set(srcs "src/led_strip_api.c")
+
+if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.0")
+ if(CONFIG_SOC_RMT_SUPPORTED)
+ list(APPEND srcs "src/led_strip_rmt_dev.c" "src/led_strip_rmt_encoder.c")
+ endif()
+else()
+ list(APPEND srcs "src/led_strip_rmt_dev_idf4.c")
+endif()
+
+# the SPI backend driver relies on something that was added in IDF 5.1
+if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.1")
+ if(CONFIG_SOC_GPSPI_SUPPORTED)
+ list(APPEND srcs "src/led_strip_spi_dev.c")
+ endif()
+endif()
+
+idf_component_register(SRCS ${srcs}
+ INCLUDE_DIRS "include" "interface"
+ REQUIRES "driver")
diff --git a/hw/bsp/espressif/components/led_strip/LICENSE b/hw/bsp/espressif/components/led_strip/LICENSE
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/hw/bsp/espressif/components/led_strip/README.md b/hw/bsp/espressif/components/led_strip/README.md
new file mode 100644
index 000000000..543d29642
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/README.md
@@ -0,0 +1,97 @@
+# LED Strip Driver
+
+[](https://components.espressif.com/components/espressif/led_strip)
+
+This driver is designed for addressable LEDs like [WS2812](http://www.world-semi.com/Certifications/WS2812B.html), where each LED is controlled by a single data line.
+
+## Backend Controllers
+
+### The [RMT](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/rmt.html) Peripheral
+
+This is the most economical way to drive the LEDs because it only consumes one RMT channel, leaving other channels free to use. However, the memory usage increases dramatically with the number of LEDs. If the RMT hardware can't be assist by DMA, the driver will going into interrupt very frequently, thus result in a high CPU usage. What's worse, if the RMT interrupt is delayed or not serviced in time (e.g. if Wi-Fi interrupt happens on the same CPU core), the RMT transaction will be corrupted and the LEDs will display incorrect colors. If you want to use RMT to drive a large number of LEDs, you'd better to enable the DMA feature if possible [^1].
+
+#### Allocate LED Strip Object with RMT Backend
+
+```c
+#define BLINK_GPIO 0
+
+led_strip_handle_t led_strip;
+
+/* LED strip initialization with the GPIO and pixels number*/
+led_strip_config_t strip_config = {
+ .strip_gpio_num = BLINK_GPIO, // The GPIO that connected to the LED strip's data line
+ .max_leds = 1, // The number of LEDs in the strip,
+ .led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip
+ .led_model = LED_MODEL_WS2812, // LED strip model
+ .flags.invert_out = false, // whether to invert the output signal (useful when your hardware has a level inverter)
+};
+
+led_strip_rmt_config_t rmt_config = {
+#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
+ .rmt_channel = 0,
+#else
+ .clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
+ .resolution_hz = 10 * 1000 * 1000, // 10MHz
+ .flags.with_dma = false, // whether to enable the DMA feature
+#endif
+};
+ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
+```
+
+You can create multiple LED strip objects with different GPIOs and pixel numbers. The backend driver will automatically allocate the RMT channel for you if there is more available.
+
+### The [SPI](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_master.html) Peripheral
+
+SPI peripheral can also be used to generate the timing required by the LED strip. However this backend is not as economical as the RMT one, because it will take up the whole **bus**, unlike the RMT just takes one **channel**. You **CAN'T** connect other devices to the same SPI bus if it's been used by the led_strip, because the led_strip doesn't have the concept of "Chip Select".
+
+Please note, the SPI backend has a dependency of **ESP-IDF >= 5.1**
+
+#### Allocate LED Strip Object with SPI Backend
+
+```c
+#define BLINK_GPIO 0
+
+led_strip_handle_t led_strip;
+
+/* LED strip initialization with the GPIO and pixels number*/
+led_strip_config_t strip_config = {
+ .strip_gpio_num = BLINK_GPIO, // The GPIO that connected to the LED strip's data line
+ .max_leds = 1, // The number of LEDs in the strip,
+ .led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip
+ .led_model = LED_MODEL_WS2812, // LED strip model
+ .flags.invert_out = false, // whether to invert the output signal (useful when your hardware has a level inverter)
+};
+
+led_strip_spi_config_t spi_config = {
+ .clk_src = SPI_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
+ .flags.with_dma = true, // Using DMA can improve performance and help drive more LEDs
+ .spi_bus = SPI2_HOST, // SPI bus ID
+};
+ESP_ERROR_CHECK(led_strip_new_spi_device(&strip_config, &spi_config, &led_strip));
+```
+
+The number of LED strip objects can be created depends on how many free SPI buses are free to use in your project.
+
+## FAQ
+
+* Which led_strip backend should I choose?
+ * It depends on your application requirement and target chip's ability.
+
+ ```mermaid
+ flowchart LR
+ A{Is RMT supported?}
+ A --> |No| B[SPI backend]
+ B --> C{Does the led strip has \n a larger number of LEDs?}
+ C --> |No| D[Don't have to enable the DMA of the backend]
+ C --> |Yes| E[Enable the DMA of the backend]
+ A --> |Yes| F{Does the led strip has \n a larger number of LEDs?}
+ F --> |Yes| G{Does RMT support DMA?}
+ G --> |Yes| E
+ G --> |No| B
+ F --> |No| H[RMT backend] --> D
+ ```
+
+* How to set the brightness of the LED strip?
+ * You can tune the brightness by scaling the value of each R-G-B element with a **same** factor. But pay attention to the overflow of the value.
+
+[^1]: The RMT DMA feature is not available on all ESP chips. Please check the data sheet before using it.
diff --git a/hw/bsp/espressif/components/led_strip/api.md b/hw/bsp/espressif/components/led_strip/api.md
new file mode 100644
index 000000000..6581d6604
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/api.md
@@ -0,0 +1,454 @@
+# API Reference
+
+## Header files
+
+- [include/led_strip.h](#file-includeled_striph)
+- [include/led_strip_rmt.h](#file-includeled_strip_rmth)
+- [include/led_strip_spi.h](#file-includeled_strip_spih)
+- [include/led_strip_types.h](#file-includeled_strip_typesh)
+- [interface/led_strip_interface.h](#file-interfaceled_strip_interfaceh)
+
+## File include/led_strip.h
+
+## Functions
+
+| Type | Name |
+| ---: | :--- |
+| esp\_err\_t | [**led\_strip\_clear**](#function-led_strip_clear) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip)
_Clear LED strip (turn off all LEDs)_ |
+| esp\_err\_t | [**led\_strip\_del**](#function-led_strip_del) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip)
_Free LED strip resources._ |
+| esp\_err\_t | [**led\_strip\_refresh**](#function-led_strip_refresh) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip)
_Refresh memory colors to LEDs._ |
+| esp\_err\_t | [**led\_strip\_set\_pixel**](#function-led_strip_set_pixel) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip, uint32\_t index, uint32\_t red, uint32\_t green, uint32\_t blue)
_Set RGB for a specific pixel._ |
+| esp\_err\_t | [**led\_strip\_set\_pixel\_hsv**](#function-led_strip_set_pixel_hsv) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip, uint32\_t index, uint16\_t hue, uint8\_t saturation, uint8\_t value)
_Set HSV for a specific pixel._ |
+| esp\_err\_t | [**led\_strip\_set\_pixel\_rgbw**](#function-led_strip_set_pixel_rgbw) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip, uint32\_t index, uint32\_t red, uint32\_t green, uint32\_t blue, uint32\_t white)
_Set RGBW for a specific pixel._ |
+
+## Functions Documentation
+
+### function `led_strip_clear`
+
+_Clear LED strip (turn off all LEDs)_
+
+```c
+esp_err_t led_strip_clear (
+ led_strip_handle_t strip
+)
+```
+
+**Parameters:**
+
+- `strip` LED strip
+
+**Returns:**
+
+- ESP\_OK: Clear LEDs successfully
+- ESP\_FAIL: Clear LEDs failed because some other error occurred
+
+### function `led_strip_del`
+
+_Free LED strip resources._
+
+```c
+esp_err_t led_strip_del (
+ led_strip_handle_t strip
+)
+```
+
+**Parameters:**
+
+- `strip` LED strip
+
+**Returns:**
+
+- ESP\_OK: Free resources successfully
+- ESP\_FAIL: Free resources failed because error occurred
+
+### function `led_strip_refresh`
+
+_Refresh memory colors to LEDs._
+
+```c
+esp_err_t led_strip_refresh (
+ led_strip_handle_t strip
+)
+```
+
+**Parameters:**
+
+- `strip` LED strip
+
+**Returns:**
+
+- ESP\_OK: Refresh successfully
+- ESP\_FAIL: Refresh failed because some other error occurred
+
+**Note:**
+
+: After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip.
+
+### function `led_strip_set_pixel`
+
+_Set RGB for a specific pixel._
+
+```c
+esp_err_t led_strip_set_pixel (
+ led_strip_handle_t strip,
+ uint32_t index,
+ uint32_t red,
+ uint32_t green,
+ uint32_t blue
+)
+```
+
+**Parameters:**
+
+- `strip` LED strip
+- `index` index of pixel to set
+- `red` red part of color
+- `green` green part of color
+- `blue` blue part of color
+
+**Returns:**
+
+- ESP\_OK: Set RGB for a specific pixel successfully
+- ESP\_ERR\_INVALID\_ARG: Set RGB for a specific pixel failed because of invalid parameters
+- ESP\_FAIL: Set RGB for a specific pixel failed because other error occurred
+
+### function `led_strip_set_pixel_hsv`
+
+_Set HSV for a specific pixel._
+
+```c
+esp_err_t led_strip_set_pixel_hsv (
+ led_strip_handle_t strip,
+ uint32_t index,
+ uint16_t hue,
+ uint8_t saturation,
+ uint8_t value
+)
+```
+
+**Parameters:**
+
+- `strip` LED strip
+- `index` index of pixel to set
+- `hue` hue part of color (0 - 360)
+- `saturation` saturation part of color (0 - 255)
+- `value` value part of color (0 - 255)
+
+**Returns:**
+
+- ESP\_OK: Set HSV color for a specific pixel successfully
+- ESP\_ERR\_INVALID\_ARG: Set HSV color for a specific pixel failed because of an invalid argument
+- ESP\_FAIL: Set HSV color for a specific pixel failed because other error occurred
+
+### function `led_strip_set_pixel_rgbw`
+
+_Set RGBW for a specific pixel._
+
+```c
+esp_err_t led_strip_set_pixel_rgbw (
+ led_strip_handle_t strip,
+ uint32_t index,
+ uint32_t red,
+ uint32_t green,
+ uint32_t blue,
+ uint32_t white
+)
+```
+
+**Note:**
+
+Only call this function if your led strip does have the white component (e.g. SK6812-RGBW)
+
+**Note:**
+
+Also see `led_strip_set_pixel` if you only want to specify the RGB part of the color and bypass the white component
+
+**Parameters:**
+
+- `strip` LED strip
+- `index` index of pixel to set
+- `red` red part of color
+- `green` green part of color
+- `blue` blue part of color
+- `white` separate white component
+
+**Returns:**
+
+- ESP\_OK: Set RGBW color for a specific pixel successfully
+- ESP\_ERR\_INVALID\_ARG: Set RGBW color for a specific pixel failed because of an invalid argument
+- ESP\_FAIL: Set RGBW color for a specific pixel failed because other error occurred
+
+## File include/led_strip_rmt.h
+
+## Structures and Types
+
+| Type | Name |
+| ---: | :--- |
+| struct | [**led\_strip\_rmt\_config\_t**](#struct-led_strip_rmt_config_t)
_LED Strip RMT specific configuration._ |
+
+## Functions
+
+| Type | Name |
+| ---: | :--- |
+| esp\_err\_t | [**led\_strip\_new\_rmt\_device**](#function-led_strip_new_rmt_device) (const [**led\_strip\_config\_t**](#struct-led_strip_config_t) \*led\_config, const [**led\_strip\_rmt\_config\_t**](#struct-led_strip_rmt_config_t) \*rmt\_config, [**led\_strip\_handle\_t**](#struct-led_strip_t) \*ret\_strip)
_Create LED strip based on RMT TX channel._ |
+
+## Structures and Types Documentation
+
+### struct `led_strip_rmt_config_t`
+
+_LED Strip RMT specific configuration._
+
+Variables:
+
+- rmt\_clock\_source\_t clk_src
RMT clock source
+
+- struct [**led\_strip\_rmt\_config\_t**](#struct-led_strip_rmt_config_t) flags
Extra driver flags
+
+- size\_t mem_block_symbols
How many RMT symbols can one RMT channel hold at one time. Set to 0 will fallback to use the default size.
+
+- uint32\_t resolution_hz
RMT tick resolution, if set to zero, a default resolution (10MHz) will be applied
+
+- uint32\_t with_dma
Use DMA to transmit data
+
+## Functions Documentation
+
+### function `led_strip_new_rmt_device`
+
+_Create LED strip based on RMT TX channel._
+
+```c
+esp_err_t led_strip_new_rmt_device (
+ const led_strip_config_t *led_config,
+ const led_strip_rmt_config_t *rmt_config,
+ led_strip_handle_t *ret_strip
+)
+```
+
+**Parameters:**
+
+- `led_config` LED strip configuration
+- `rmt_config` RMT specific configuration
+- `ret_strip` Returned LED strip handle
+
+**Returns:**
+
+- ESP\_OK: create LED strip handle successfully
+- ESP\_ERR\_INVALID\_ARG: create LED strip handle failed because of invalid argument
+- ESP\_ERR\_NO\_MEM: create LED strip handle failed because of out of memory
+- ESP\_FAIL: create LED strip handle failed because some other error
+
+## File include/led_strip_spi.h
+
+## Structures and Types
+
+| Type | Name |
+| ---: | :--- |
+| struct | [**led\_strip\_spi\_config\_t**](#struct-led_strip_spi_config_t)
_LED Strip SPI specific configuration._ |
+
+## Functions
+
+| Type | Name |
+| ---: | :--- |
+| esp\_err\_t | [**led\_strip\_new\_spi\_device**](#function-led_strip_new_spi_device) (const [**led\_strip\_config\_t**](#struct-led_strip_config_t) \*led\_config, const [**led\_strip\_spi\_config\_t**](#struct-led_strip_spi_config_t) \*spi\_config, [**led\_strip\_handle\_t**](#struct-led_strip_t) \*ret\_strip)
_Create LED strip based on SPI MOSI channel._ |
+
+## Structures and Types Documentation
+
+### struct `led_strip_spi_config_t`
+
+_LED Strip SPI specific configuration._
+
+Variables:
+
+- spi\_clock\_source\_t clk_src
SPI clock source
+
+- struct [**led\_strip\_spi\_config\_t**](#struct-led_strip_spi_config_t) flags
Extra driver flags
+
+- spi\_host\_device\_t spi_bus
SPI bus ID. Which buses are available depends on the specific chip
+
+- uint32\_t with_dma
Use DMA to transmit data
+
+## Functions Documentation
+
+### function `led_strip_new_spi_device`
+
+_Create LED strip based on SPI MOSI channel._
+
+```c
+esp_err_t led_strip_new_spi_device (
+ const led_strip_config_t *led_config,
+ const led_strip_spi_config_t *spi_config,
+ led_strip_handle_t *ret_strip
+)
+```
+
+**Note:**
+
+Although only the MOSI line is used for generating the signal, the whole SPI bus can't be used for other purposes.
+
+**Parameters:**
+
+- `led_config` LED strip configuration
+- `spi_config` SPI specific configuration
+- `ret_strip` Returned LED strip handle
+
+**Returns:**
+
+- ESP\_OK: create LED strip handle successfully
+- ESP\_ERR\_INVALID\_ARG: create LED strip handle failed because of invalid argument
+- ESP\_ERR\_NOT\_SUPPORTED: create LED strip handle failed because of unsupported configuration
+- ESP\_ERR\_NO\_MEM: create LED strip handle failed because of out of memory
+- ESP\_FAIL: create LED strip handle failed because some other error
+
+## File include/led_strip_types.h
+
+## Structures and Types
+
+| Type | Name |
+| ---: | :--- |
+| enum | [**led\_model\_t**](#enum-led_model_t)
_LED strip model._ |
+| enum | [**led\_pixel\_format\_t**](#enum-led_pixel_format_t)
_LED strip pixel format._ |
+| struct | [**led\_strip\_config\_t**](#struct-led_strip_config_t)
_LED Strip Configuration._ |
+| typedef struct [**led\_strip\_t**](#struct-led_strip_t) \* | [**led\_strip\_handle\_t**](#typedef-led_strip_handle_t)
_LED strip handle._ |
+
+## Structures and Types Documentation
+
+### enum `led_model_t`
+
+_LED strip model._
+
+```c
+enum led_model_t {
+ LED_MODEL_WS2812,
+ LED_MODEL_SK6812,
+ LED_MODEL_INVALID
+};
+```
+
+**Note:**
+
+Different led model may have different timing parameters, so we need to distinguish them.
+
+### enum `led_pixel_format_t`
+
+_LED strip pixel format._
+
+```c
+enum led_pixel_format_t {
+ LED_PIXEL_FORMAT_GRB,
+ LED_PIXEL_FORMAT_GRBW,
+ LED_PIXEL_FORMAT_INVALID
+};
+```
+
+### struct `led_strip_config_t`
+
+_LED Strip Configuration._
+
+Variables:
+
+- struct [**led\_strip\_config\_t**](#struct-led_strip_config_t) flags
Extra driver flags
+
+- uint32\_t invert_out
Invert output signal
+
+- led\_model\_t led_model
LED model
+
+- led\_pixel\_format\_t led_pixel_format
LED pixel format
+
+- uint32\_t max_leds
Maximum LEDs in a single strip
+
+- int strip_gpio_num
GPIO number that used by LED strip
+
+### typedef `led_strip_handle_t`
+
+_LED strip handle._
+
+```c
+typedef struct led_strip_t* led_strip_handle_t;
+```
+
+## File interface/led_strip_interface.h
+
+## Structures and Types
+
+| Type | Name |
+| ---: | :--- |
+| struct | [**led\_strip\_t**](#struct-led_strip_t)
_LED strip interface definition._ |
+| typedef struct [**led\_strip\_t**](#struct-led_strip_t) | [**led\_strip\_t**](#typedef-led_strip_t)
|
+
+## Structures and Types Documentation
+
+### struct `led_strip_t`
+
+_LED strip interface definition._
+
+Variables:
+
+- esp\_err\_t(\* clear
_Clear LED strip (turn off all LEDs)_
**Parameters:**
+
+- `strip` LED strip
+- `timeout_ms` timeout value for clearing task
+
+**Returns:**
+
+- ESP\_OK: Clear LEDs successfully
+- ESP\_FAIL: Clear LEDs failed because some other error occurred
+
+- esp\_err\_t(\* del
_Free LED strip resources._
**Parameters:**
+
+- `strip` LED strip
+
+**Returns:**
+
+- ESP\_OK: Free resources successfully
+- ESP\_FAIL: Free resources failed because error occurred
+
+- esp\_err\_t(\* refresh
_Refresh memory colors to LEDs._
**Parameters:**
+
+- `strip` LED strip
+- `timeout_ms` timeout value for refreshing task
+
+**Returns:**
+
+- ESP\_OK: Refresh successfully
+- ESP\_FAIL: Refresh failed because some other error occurred
+
+**Note:**
+
+: After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip.
+
+- esp\_err\_t(\* set_pixel
_Set RGB for a specific pixel._
**Parameters:**
+
+- `strip` LED strip
+- `index` index of pixel to set
+- `red` red part of color
+- `green` green part of color
+- `blue` blue part of color
+
+**Returns:**
+
+- ESP\_OK: Set RGB for a specific pixel successfully
+- ESP\_ERR\_INVALID\_ARG: Set RGB for a specific pixel failed because of invalid parameters
+- ESP\_FAIL: Set RGB for a specific pixel failed because other error occurred
+
+- esp\_err\_t(\* set_pixel_rgbw
_Set RGBW for a specific pixel. Similar to_ `set_pixel`_but also set the white component._
**Parameters:**
+
+- `strip` LED strip
+- `index` index of pixel to set
+- `red` red part of color
+- `green` green part of color
+- `blue` blue part of color
+- `white` separate white component
+
+**Returns:**
+
+- ESP\_OK: Set RGBW color for a specific pixel successfully
+- ESP\_ERR\_INVALID\_ARG: Set RGBW color for a specific pixel failed because of an invalid argument
+- ESP\_FAIL: Set RGBW color for a specific pixel failed because other error occurred
+
+### typedef `led_strip_t`
+
+```c
+typedef struct led_strip_t led_strip_t;
+```
+
+Type of LED strip
diff --git a/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/CMakeLists.txt b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/CMakeLists.txt
new file mode 100644
index 000000000..923c46310
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/CMakeLists.txt
@@ -0,0 +1,9 @@
+# For more information about build system see
+# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
+# The following five lines of boilerplate have to be in your project's
+# CMakeLists in this exact order for cmake to work correctly
+cmake_minimum_required(VERSION 3.16)
+
+set(IDF_TARGET "esp32s3")
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(led_strip_rmt_ws2812)
diff --git a/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/README.md b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/README.md
new file mode 100644
index 000000000..ad52235d5
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/README.md
@@ -0,0 +1,31 @@
+# LED Strip Example (RMT backend + WS2812)
+
+This example demonstrates how to blink the WS2812 LED using the [led_strip](https://components.espressif.com/component/espressif/led_strip) component.
+
+## How to Use Example
+
+### Hardware Required
+
+* A development board with Espressif SoC
+* A USB cable for Power supply and programming
+* WS2812 LED strip
+
+### Configure the Example
+
+Before project configuration and build, be sure to set the correct chip target using `idf.py set-target `. Then assign the proper GPIO in the [source file](main/led_strip_rmt_ws2812_main.c). If your led strip has multiple LEDs, don't forget update the number.
+
+### Build and Flash
+
+Run `idf.py -p PORT build flash monitor` to build, flash and monitor the project.
+
+(To exit the serial monitor, type ``Ctrl-]``.)
+
+See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
+
+## Example Output
+
+```text
+I (299) gpio: GPIO[8]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
+I (309) example: Created LED strip object with RMT backend
+I (309) example: Start blinking LED strip
+```
diff --git a/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/dependencies.lock b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/dependencies.lock
new file mode 100644
index 000000000..97840a153
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/dependencies.lock
@@ -0,0 +1,15 @@
+dependencies:
+ espressif/led_strip:
+ component_hash: null
+ source:
+ path: /home/hathach/code/idf-extra-components/led_strip
+ type: local
+ version: 2.5.2
+ idf:
+ component_hash: null
+ source:
+ type: idf
+ version: 5.1.1
+manifest_hash: 47d47762be26168b388cb0e6cbfee6b22c68d630ebf4b27a49c47c4c54191590
+target: esp32s3
+version: 1.0.0
diff --git a/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/CMakeLists.txt b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/CMakeLists.txt
new file mode 100644
index 000000000..37b9c1458
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/CMakeLists.txt
@@ -0,0 +1,2 @@
+idf_component_register(SRCS "led_strip_rmt_ws2812_main.c"
+ INCLUDE_DIRS ".")
diff --git a/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/idf_component.yml b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/idf_component.yml
new file mode 100644
index 000000000..916c366c7
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/idf_component.yml
@@ -0,0 +1,5 @@
+## IDF Component Manager Manifest File
+dependencies:
+ espressif/led_strip:
+ version: '^2'
+ override_path: '../../../'
diff --git a/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/led_strip_rmt_ws2812_main.c b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/led_strip_rmt_ws2812_main.c
new file mode 100644
index 000000000..4b20a5958
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/led_strip_rmt_ws2812_main.c
@@ -0,0 +1,75 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
+ */
+#include
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "led_strip.h"
+#include "esp_log.h"
+#include "esp_err.h"
+
+// GPIO assignment
+#define LED_STRIP_BLINK_GPIO 48
+// Numbers of the LED in the strip
+#define LED_STRIP_LED_NUMBERS 1
+// 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution)
+#define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000)
+
+static const char *TAG = "example";
+
+led_strip_handle_t configure_led(void)
+{
+ // LED strip general initialization, according to your led board design
+ led_strip_config_t strip_config = {
+ .strip_gpio_num = LED_STRIP_BLINK_GPIO, // The GPIO that connected to the LED strip's data line
+ .max_leds = LED_STRIP_LED_NUMBERS, // The number of LEDs in the strip,
+ .led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip
+ .led_model = LED_MODEL_WS2812, // LED strip model
+ .flags.invert_out = false, // whether to invert the output signal
+ };
+
+ // LED strip backend configuration: RMT
+ led_strip_rmt_config_t rmt_config = {
+#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
+ .rmt_channel = 0,
+#else
+ .clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
+ .resolution_hz = LED_STRIP_RMT_RES_HZ, // RMT counter clock frequency
+ .flags.with_dma = false, // DMA feature is available on ESP target like ESP32-S3
+#endif
+ };
+
+ // LED Strip object handle
+ led_strip_handle_t led_strip;
+ ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
+ ESP_LOGI(TAG, "Created LED strip object with RMT backend");
+ return led_strip;
+}
+
+void app_main(void)
+{
+ led_strip_handle_t led_strip = configure_led();
+ bool led_on_off = false;
+
+ ESP_LOGI(TAG, "Start blinking LED strip");
+ while (1) {
+ if (led_on_off) {
+ /* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */
+ for (int i = 0; i < LED_STRIP_LED_NUMBERS; i++) {
+ ESP_ERROR_CHECK(led_strip_set_pixel(led_strip, i, 5, 5, 5));
+ }
+ /* Refresh the strip to send data */
+ ESP_ERROR_CHECK(led_strip_refresh(led_strip));
+ ESP_LOGI(TAG, "LED ON!");
+ } else {
+ /* Set all LED off to clear all pixels */
+ ESP_ERROR_CHECK(led_strip_clear(led_strip));
+ ESP_LOGI(TAG, "LED OFF!");
+ }
+
+ led_on_off = !led_on_off;
+ vTaskDelay(pdMS_TO_TICKS(500));
+ }
+}
diff --git a/hw/bsp/espressif/components/led_strip/idf_component.yml b/hw/bsp/espressif/components/led_strip/idf_component.yml
new file mode 100644
index 000000000..1fd9b83ee
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/idf_component.yml
@@ -0,0 +1,5 @@
+version: "2.5.2"
+description: Driver for Addressable LED Strip (WS2812, etc)
+url: https://github.com/espressif/idf-extra-components/tree/master/led_strip
+dependencies:
+ idf: ">=4.4"
diff --git a/hw/bsp/espressif/components/led_strip/include/led_strip.h b/hw/bsp/espressif/components/led_strip/include/led_strip.h
new file mode 100644
index 000000000..38711744a
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/include/led_strip.h
@@ -0,0 +1,111 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include
+#include "esp_err.h"
+#include "led_strip_rmt.h"
+#include "esp_idf_version.h"
+
+#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)
+#include "led_strip_spi.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Set RGB for a specific pixel
+ *
+ * @param strip: LED strip
+ * @param index: index of pixel to set
+ * @param red: red part of color
+ * @param green: green part of color
+ * @param blue: blue part of color
+ *
+ * @return
+ * - ESP_OK: Set RGB for a specific pixel successfully
+ * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters
+ * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred
+ */
+esp_err_t led_strip_set_pixel(led_strip_handle_t strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue);
+
+/**
+ * @brief Set RGBW for a specific pixel
+ *
+ * @note Only call this function if your led strip does have the white component (e.g. SK6812-RGBW)
+ * @note Also see `led_strip_set_pixel` if you only want to specify the RGB part of the color and bypass the white component
+ *
+ * @param strip: LED strip
+ * @param index: index of pixel to set
+ * @param red: red part of color
+ * @param green: green part of color
+ * @param blue: blue part of color
+ * @param white: separate white component
+ *
+ * @return
+ * - ESP_OK: Set RGBW color for a specific pixel successfully
+ * - ESP_ERR_INVALID_ARG: Set RGBW color for a specific pixel failed because of an invalid argument
+ * - ESP_FAIL: Set RGBW color for a specific pixel failed because other error occurred
+ */
+esp_err_t led_strip_set_pixel_rgbw(led_strip_handle_t strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue, uint32_t white);
+
+/**
+ * @brief Set HSV for a specific pixel
+ *
+ * @param strip: LED strip
+ * @param index: index of pixel to set
+ * @param hue: hue part of color (0 - 360)
+ * @param saturation: saturation part of color (0 - 255)
+ * @param value: value part of color (0 - 255)
+ *
+ * @return
+ * - ESP_OK: Set HSV color for a specific pixel successfully
+ * - ESP_ERR_INVALID_ARG: Set HSV color for a specific pixel failed because of an invalid argument
+ * - ESP_FAIL: Set HSV color for a specific pixel failed because other error occurred
+ */
+esp_err_t led_strip_set_pixel_hsv(led_strip_handle_t strip, uint32_t index, uint16_t hue, uint8_t saturation, uint8_t value);
+
+/**
+ * @brief Refresh memory colors to LEDs
+ *
+ * @param strip: LED strip
+ *
+ * @return
+ * - ESP_OK: Refresh successfully
+ * - ESP_FAIL: Refresh failed because some other error occurred
+ *
+ * @note:
+ * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip.
+ */
+esp_err_t led_strip_refresh(led_strip_handle_t strip);
+
+/**
+ * @brief Clear LED strip (turn off all LEDs)
+ *
+ * @param strip: LED strip
+ *
+ * @return
+ * - ESP_OK: Clear LEDs successfully
+ * - ESP_FAIL: Clear LEDs failed because some other error occurred
+ */
+esp_err_t led_strip_clear(led_strip_handle_t strip);
+
+/**
+ * @brief Free LED strip resources
+ *
+ * @param strip: LED strip
+ *
+ * @return
+ * - ESP_OK: Free resources successfully
+ * - ESP_FAIL: Free resources failed because error occurred
+ */
+esp_err_t led_strip_del(led_strip_handle_t strip);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/hw/bsp/espressif/components/led_strip/include/led_strip_rmt.h b/hw/bsp/espressif/components/led_strip/include/led_strip_rmt.h
new file mode 100644
index 000000000..b575aeaba
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/include/led_strip_rmt.h
@@ -0,0 +1,53 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include
+#include "esp_err.h"
+#include "led_strip_types.h"
+#include "esp_idf_version.h"
+
+#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
+#include "driver/rmt_types.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief LED Strip RMT specific configuration
+ */
+typedef struct {
+#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
+ uint8_t rmt_channel; /*!< Specify the channel number, the legacy RMT driver doesn't support channel allocator */
+#else // new driver supports specify the clock source and clock resolution
+ rmt_clock_source_t clk_src; /*!< RMT clock source */
+ uint32_t resolution_hz; /*!< RMT tick resolution, if set to zero, a default resolution (10MHz) will be applied */
+#endif
+ size_t mem_block_symbols; /*!< How many RMT symbols can one RMT channel hold at one time. Set to 0 will fallback to use the default size. */
+ struct {
+ uint32_t with_dma: 1; /*!< Use DMA to transmit data */
+ } flags; /*!< Extra driver flags */
+} led_strip_rmt_config_t;
+
+/**
+ * @brief Create LED strip based on RMT TX channel
+ *
+ * @param led_config LED strip configuration
+ * @param rmt_config RMT specific configuration
+ * @param ret_strip Returned LED strip handle
+ * @return
+ * - ESP_OK: create LED strip handle successfully
+ * - ESP_ERR_INVALID_ARG: create LED strip handle failed because of invalid argument
+ * - ESP_ERR_NO_MEM: create LED strip handle failed because of out of memory
+ * - ESP_FAIL: create LED strip handle failed because some other error
+ */
+esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const led_strip_rmt_config_t *rmt_config, led_strip_handle_t *ret_strip);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/hw/bsp/espressif/components/led_strip/include/led_strip_spi.h b/hw/bsp/espressif/components/led_strip/include/led_strip_spi.h
new file mode 100644
index 000000000..eb3524936
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/include/led_strip_spi.h
@@ -0,0 +1,46 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include
+#include "esp_err.h"
+#include "driver/spi_master.h"
+#include "led_strip_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief LED Strip SPI specific configuration
+ */
+typedef struct {
+ spi_clock_source_t clk_src; /*!< SPI clock source */
+ spi_host_device_t spi_bus; /*!< SPI bus ID. Which buses are available depends on the specific chip */
+ struct {
+ uint32_t with_dma: 1; /*!< Use DMA to transmit data */
+ } flags; /*!< Extra driver flags */
+} led_strip_spi_config_t;
+
+/**
+ * @brief Create LED strip based on SPI MOSI channel
+ * @note Although only the MOSI line is used for generating the signal, the whole SPI bus can't be used for other purposes.
+ *
+ * @param led_config LED strip configuration
+ * @param spi_config SPI specific configuration
+ * @param ret_strip Returned LED strip handle
+ * @return
+ * - ESP_OK: create LED strip handle successfully
+ * - ESP_ERR_INVALID_ARG: create LED strip handle failed because of invalid argument
+ * - ESP_ERR_NOT_SUPPORTED: create LED strip handle failed because of unsupported configuration
+ * - ESP_ERR_NO_MEM: create LED strip handle failed because of out of memory
+ * - ESP_FAIL: create LED strip handle failed because some other error
+ */
+esp_err_t led_strip_new_spi_device(const led_strip_config_t *led_config, const led_strip_spi_config_t *spi_config, led_strip_handle_t *ret_strip);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/hw/bsp/espressif/components/led_strip/include/led_strip_types.h b/hw/bsp/espressif/components/led_strip/include/led_strip_types.h
new file mode 100644
index 000000000..691f0bc39
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/include/led_strip_types.h
@@ -0,0 +1,54 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief LED strip pixel format
+ */
+typedef enum {
+ LED_PIXEL_FORMAT_GRB, /*!< Pixel format: GRB */
+ LED_PIXEL_FORMAT_GRBW, /*!< Pixel format: GRBW */
+ LED_PIXEL_FORMAT_INVALID /*!< Invalid pixel format */
+} led_pixel_format_t;
+
+/**
+ * @brief LED strip model
+ * @note Different led model may have different timing parameters, so we need to distinguish them.
+ */
+typedef enum {
+ LED_MODEL_WS2812, /*!< LED strip model: WS2812 */
+ LED_MODEL_SK6812, /*!< LED strip model: SK6812 */
+ LED_MODEL_INVALID /*!< Invalid LED strip model */
+} led_model_t;
+
+/**
+ * @brief LED strip handle
+ */
+typedef struct led_strip_t *led_strip_handle_t;
+
+/**
+ * @brief LED Strip Configuration
+ */
+typedef struct {
+ int strip_gpio_num; /*!< GPIO number that used by LED strip */
+ uint32_t max_leds; /*!< Maximum LEDs in a single strip */
+ led_pixel_format_t led_pixel_format; /*!< LED pixel format */
+ led_model_t led_model; /*!< LED model */
+
+ struct {
+ uint32_t invert_out: 1; /*!< Invert output signal */
+ } flags; /*!< Extra driver flags */
+} led_strip_config_t;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/hw/bsp/espressif/components/led_strip/interface/led_strip_interface.h b/hw/bsp/espressif/components/led_strip/interface/led_strip_interface.h
new file mode 100644
index 000000000..3de4c2715
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/interface/led_strip_interface.h
@@ -0,0 +1,95 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct led_strip_t led_strip_t; /*!< Type of LED strip */
+
+/**
+ * @brief LED strip interface definition
+ */
+struct led_strip_t {
+ /**
+ * @brief Set RGB for a specific pixel
+ *
+ * @param strip: LED strip
+ * @param index: index of pixel to set
+ * @param red: red part of color
+ * @param green: green part of color
+ * @param blue: blue part of color
+ *
+ * @return
+ * - ESP_OK: Set RGB for a specific pixel successfully
+ * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters
+ * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred
+ */
+ esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue);
+
+ /**
+ * @brief Set RGBW for a specific pixel. Similar to `set_pixel` but also set the white component
+ *
+ * @param strip: LED strip
+ * @param index: index of pixel to set
+ * @param red: red part of color
+ * @param green: green part of color
+ * @param blue: blue part of color
+ * @param white: separate white component
+ *
+ * @return
+ * - ESP_OK: Set RGBW color for a specific pixel successfully
+ * - ESP_ERR_INVALID_ARG: Set RGBW color for a specific pixel failed because of an invalid argument
+ * - ESP_FAIL: Set RGBW color for a specific pixel failed because other error occurred
+ */
+ esp_err_t (*set_pixel_rgbw)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue, uint32_t white);
+
+ /**
+ * @brief Refresh memory colors to LEDs
+ *
+ * @param strip: LED strip
+ * @param timeout_ms: timeout value for refreshing task
+ *
+ * @return
+ * - ESP_OK: Refresh successfully
+ * - ESP_FAIL: Refresh failed because some other error occurred
+ *
+ * @note:
+ * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip.
+ */
+ esp_err_t (*refresh)(led_strip_t *strip);
+
+ /**
+ * @brief Clear LED strip (turn off all LEDs)
+ *
+ * @param strip: LED strip
+ * @param timeout_ms: timeout value for clearing task
+ *
+ * @return
+ * - ESP_OK: Clear LEDs successfully
+ * - ESP_FAIL: Clear LEDs failed because some other error occurred
+ */
+ esp_err_t (*clear)(led_strip_t *strip);
+
+ /**
+ * @brief Free LED strip resources
+ *
+ * @param strip: LED strip
+ *
+ * @return
+ * - ESP_OK: Free resources successfully
+ * - ESP_FAIL: Free resources failed because error occurred
+ */
+ esp_err_t (*del)(led_strip_t *strip);
+};
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/hw/bsp/espressif/components/led_strip/src/led_strip_api.c b/hw/bsp/espressif/components/led_strip/src/led_strip_api.c
new file mode 100644
index 000000000..6eb86b8f1
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/src/led_strip_api.c
@@ -0,0 +1,94 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "esp_log.h"
+#include "esp_check.h"
+#include "led_strip.h"
+#include "led_strip_interface.h"
+
+static const char *TAG = "led_strip";
+
+esp_err_t led_strip_set_pixel(led_strip_handle_t strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue)
+{
+ ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+ return strip->set_pixel(strip, index, red, green, blue);
+}
+
+esp_err_t led_strip_set_pixel_hsv(led_strip_handle_t strip, uint32_t index, uint16_t hue, uint8_t saturation, uint8_t value)
+{
+ ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+
+ uint32_t red = 0;
+ uint32_t green = 0;
+ uint32_t blue = 0;
+
+ uint32_t rgb_max = value;
+ uint32_t rgb_min = rgb_max * (255 - saturation) / 255.0f;
+
+ uint32_t i = hue / 60;
+ uint32_t diff = hue % 60;
+
+ // RGB adjustment amount by hue
+ uint32_t rgb_adj = (rgb_max - rgb_min) * diff / 60;
+
+ switch (i) {
+ case 0:
+ red = rgb_max;
+ green = rgb_min + rgb_adj;
+ blue = rgb_min;
+ break;
+ case 1:
+ red = rgb_max - rgb_adj;
+ green = rgb_max;
+ blue = rgb_min;
+ break;
+ case 2:
+ red = rgb_min;
+ green = rgb_max;
+ blue = rgb_min + rgb_adj;
+ break;
+ case 3:
+ red = rgb_min;
+ green = rgb_max - rgb_adj;
+ blue = rgb_max;
+ break;
+ case 4:
+ red = rgb_min + rgb_adj;
+ green = rgb_min;
+ blue = rgb_max;
+ break;
+ default:
+ red = rgb_max;
+ green = rgb_min;
+ blue = rgb_max - rgb_adj;
+ break;
+ }
+
+ return strip->set_pixel(strip, index, red, green, blue);
+}
+
+esp_err_t led_strip_set_pixel_rgbw(led_strip_handle_t strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue, uint32_t white)
+{
+ ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+ return strip->set_pixel_rgbw(strip, index, red, green, blue, white);
+}
+
+esp_err_t led_strip_refresh(led_strip_handle_t strip)
+{
+ ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+ return strip->refresh(strip);
+}
+
+esp_err_t led_strip_clear(led_strip_handle_t strip)
+{
+ ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+ return strip->clear(strip);
+}
+
+esp_err_t led_strip_del(led_strip_handle_t strip)
+{
+ ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+ return strip->del(strip);
+}
diff --git a/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev.c b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev.c
new file mode 100644
index 000000000..1cbf0e45a
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev.c
@@ -0,0 +1,164 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include
+#include
+#include
+#include "esp_log.h"
+#include "esp_check.h"
+#include "driver/rmt_tx.h"
+#include "led_strip.h"
+#include "led_strip_interface.h"
+#include "led_strip_rmt_encoder.h"
+
+#define LED_STRIP_RMT_DEFAULT_RESOLUTION 10000000 // 10MHz resolution
+#define LED_STRIP_RMT_DEFAULT_TRANS_QUEUE_SIZE 4
+// the memory size of each RMT channel, in words (4 bytes)
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
+#define LED_STRIP_RMT_DEFAULT_MEM_BLOCK_SYMBOLS 64
+#else
+#define LED_STRIP_RMT_DEFAULT_MEM_BLOCK_SYMBOLS 48
+#endif
+
+static const char *TAG = "led_strip_rmt";
+
+typedef struct {
+ led_strip_t base;
+ rmt_channel_handle_t rmt_chan;
+ rmt_encoder_handle_t strip_encoder;
+ uint32_t strip_len;
+ uint8_t bytes_per_pixel;
+ uint8_t pixel_buf[];
+} led_strip_rmt_obj;
+
+static esp_err_t led_strip_rmt_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue)
+{
+ led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base);
+ ESP_RETURN_ON_FALSE(index < rmt_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of maximum number of LEDs");
+ uint32_t start = index * rmt_strip->bytes_per_pixel;
+ // In thr order of GRB, as LED strip like WS2812 sends out pixels in this order
+ rmt_strip->pixel_buf[start + 0] = green & 0xFF;
+ rmt_strip->pixel_buf[start + 1] = red & 0xFF;
+ rmt_strip->pixel_buf[start + 2] = blue & 0xFF;
+ if (rmt_strip->bytes_per_pixel > 3) {
+ rmt_strip->pixel_buf[start + 3] = 0;
+ }
+ return ESP_OK;
+}
+
+static esp_err_t led_strip_rmt_set_pixel_rgbw(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue, uint32_t white)
+{
+ led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base);
+ ESP_RETURN_ON_FALSE(index < rmt_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of maximum number of LEDs");
+ ESP_RETURN_ON_FALSE(rmt_strip->bytes_per_pixel == 4, ESP_ERR_INVALID_ARG, TAG, "wrong LED pixel format, expected 4 bytes per pixel");
+ uint8_t *buf_start = rmt_strip->pixel_buf + index * 4;
+ // SK6812 component order is GRBW
+ *buf_start = green & 0xFF;
+ *++buf_start = red & 0xFF;
+ *++buf_start = blue & 0xFF;
+ *++buf_start = white & 0xFF;
+ return ESP_OK;
+}
+
+static esp_err_t led_strip_rmt_refresh(led_strip_t *strip)
+{
+ led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base);
+ rmt_transmit_config_t tx_conf = {
+ .loop_count = 0,
+ };
+
+ ESP_RETURN_ON_ERROR(rmt_enable(rmt_strip->rmt_chan), TAG, "enable RMT channel failed");
+ ESP_RETURN_ON_ERROR(rmt_transmit(rmt_strip->rmt_chan, rmt_strip->strip_encoder, rmt_strip->pixel_buf,
+ rmt_strip->strip_len * rmt_strip->bytes_per_pixel, &tx_conf), TAG, "transmit pixels by RMT failed");
+ ESP_RETURN_ON_ERROR(rmt_tx_wait_all_done(rmt_strip->rmt_chan, -1), TAG, "flush RMT channel failed");
+ ESP_RETURN_ON_ERROR(rmt_disable(rmt_strip->rmt_chan), TAG, "disable RMT channel failed");
+ return ESP_OK;
+}
+
+static esp_err_t led_strip_rmt_clear(led_strip_t *strip)
+{
+ led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base);
+ // Write zero to turn off all leds
+ memset(rmt_strip->pixel_buf, 0, rmt_strip->strip_len * rmt_strip->bytes_per_pixel);
+ return led_strip_rmt_refresh(strip);
+}
+
+static esp_err_t led_strip_rmt_del(led_strip_t *strip)
+{
+ led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base);
+ ESP_RETURN_ON_ERROR(rmt_del_channel(rmt_strip->rmt_chan), TAG, "delete RMT channel failed");
+ ESP_RETURN_ON_ERROR(rmt_del_encoder(rmt_strip->strip_encoder), TAG, "delete strip encoder failed");
+ free(rmt_strip);
+ return ESP_OK;
+}
+
+esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const led_strip_rmt_config_t *rmt_config, led_strip_handle_t *ret_strip)
+{
+ led_strip_rmt_obj *rmt_strip = NULL;
+ esp_err_t ret = ESP_OK;
+ ESP_GOTO_ON_FALSE(led_config && rmt_config && ret_strip, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
+ ESP_GOTO_ON_FALSE(led_config->led_pixel_format < LED_PIXEL_FORMAT_INVALID, ESP_ERR_INVALID_ARG, err, TAG, "invalid led_pixel_format");
+ uint8_t bytes_per_pixel = 3;
+ if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRBW) {
+ bytes_per_pixel = 4;
+ } else if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRB) {
+ bytes_per_pixel = 3;
+ } else {
+ assert(false);
+ }
+ rmt_strip = calloc(1, sizeof(led_strip_rmt_obj) + led_config->max_leds * bytes_per_pixel);
+ ESP_GOTO_ON_FALSE(rmt_strip, ESP_ERR_NO_MEM, err, TAG, "no mem for rmt strip");
+ uint32_t resolution = rmt_config->resolution_hz ? rmt_config->resolution_hz : LED_STRIP_RMT_DEFAULT_RESOLUTION;
+
+ // for backward compatibility, if the user does not set the clk_src, use the default value
+ rmt_clock_source_t clk_src = RMT_CLK_SRC_DEFAULT;
+ if (rmt_config->clk_src) {
+ clk_src = rmt_config->clk_src;
+ }
+ size_t mem_block_symbols = LED_STRIP_RMT_DEFAULT_MEM_BLOCK_SYMBOLS;
+ // override the default value if the user sets it
+ if (rmt_config->mem_block_symbols) {
+ mem_block_symbols = rmt_config->mem_block_symbols;
+ }
+ rmt_tx_channel_config_t rmt_chan_config = {
+ .clk_src = clk_src,
+ .gpio_num = led_config->strip_gpio_num,
+ .mem_block_symbols = mem_block_symbols,
+ .resolution_hz = resolution,
+ .trans_queue_depth = LED_STRIP_RMT_DEFAULT_TRANS_QUEUE_SIZE,
+ .flags.with_dma = rmt_config->flags.with_dma,
+ .flags.invert_out = led_config->flags.invert_out,
+ };
+ ESP_GOTO_ON_ERROR(rmt_new_tx_channel(&rmt_chan_config, &rmt_strip->rmt_chan), err, TAG, "create RMT TX channel failed");
+
+ led_strip_encoder_config_t strip_encoder_conf = {
+ .resolution = resolution,
+ .led_model = led_config->led_model
+ };
+ ESP_GOTO_ON_ERROR(rmt_new_led_strip_encoder(&strip_encoder_conf, &rmt_strip->strip_encoder), err, TAG, "create LED strip encoder failed");
+
+
+ rmt_strip->bytes_per_pixel = bytes_per_pixel;
+ rmt_strip->strip_len = led_config->max_leds;
+ rmt_strip->base.set_pixel = led_strip_rmt_set_pixel;
+ rmt_strip->base.set_pixel_rgbw = led_strip_rmt_set_pixel_rgbw;
+ rmt_strip->base.refresh = led_strip_rmt_refresh;
+ rmt_strip->base.clear = led_strip_rmt_clear;
+ rmt_strip->base.del = led_strip_rmt_del;
+
+ *ret_strip = &rmt_strip->base;
+ return ESP_OK;
+err:
+ if (rmt_strip) {
+ if (rmt_strip->rmt_chan) {
+ rmt_del_channel(rmt_strip->rmt_chan);
+ }
+ if (rmt_strip->strip_encoder) {
+ rmt_del_encoder(rmt_strip->strip_encoder);
+ }
+ free(rmt_strip);
+ }
+ return ret;
+}
diff --git a/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev_idf4.c b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev_idf4.c
new file mode 100644
index 000000000..a1067cd7c
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev_idf4.c
@@ -0,0 +1,194 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include
+#include
+#include
+#include "esp_log.h"
+#include "esp_check.h"
+#include "driver/rmt.h"
+#include "led_strip.h"
+#include "led_strip_interface.h"
+
+static const char *TAG = "led_strip_rmt";
+
+#define WS2812_T0H_NS (300)
+#define WS2812_T0L_NS (900)
+#define WS2812_T1H_NS (900)
+#define WS2812_T1L_NS (300)
+
+#define SK6812_T0H_NS (300)
+#define SK6812_T0L_NS (900)
+#define SK6812_T1H_NS (600)
+#define SK6812_T1L_NS (600)
+
+#define LED_STRIP_RESET_MS (10)
+
+// the memory size of each RMT channel, in words (4 bytes)
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
+#define LED_STRIP_RMT_DEFAULT_MEM_BLOCK_SYMBOLS 64
+#else
+#define LED_STRIP_RMT_DEFAULT_MEM_BLOCK_SYMBOLS 48
+#endif
+
+static uint32_t led_t0h_ticks = 0;
+static uint32_t led_t1h_ticks = 0;
+static uint32_t led_t0l_ticks = 0;
+static uint32_t led_t1l_ticks = 0;
+
+typedef struct {
+ led_strip_t base;
+ rmt_channel_t rmt_channel;
+ uint32_t strip_len;
+ uint8_t bytes_per_pixel;
+ uint8_t buffer[0];
+} led_strip_rmt_obj;
+
+static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size,
+ size_t wanted_num, size_t *translated_size, size_t *item_num)
+{
+ if (src == NULL || dest == NULL) {
+ *translated_size = 0;
+ *item_num = 0;
+ return;
+ }
+ const rmt_item32_t bit0 = {{{ led_t0h_ticks, 1, led_t0l_ticks, 0 }}}; //Logical 0
+ const rmt_item32_t bit1 = {{{ led_t1h_ticks, 1, led_t1l_ticks, 0 }}}; //Logical 1
+ size_t size = 0;
+ size_t num = 0;
+ uint8_t *psrc = (uint8_t *)src;
+ rmt_item32_t *pdest = dest;
+ while (size < src_size && num < wanted_num) {
+ for (int i = 0; i < 8; i++) {
+ // MSB first
+ if (*psrc & (1 << (7 - i))) {
+ pdest->val = bit1.val;
+ } else {
+ pdest->val = bit0.val;
+ }
+ num++;
+ pdest++;
+ }
+ size++;
+ psrc++;
+ }
+ *translated_size = size;
+ *item_num = num;
+}
+
+static esp_err_t led_strip_rmt_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue)
+{
+ led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base);
+ ESP_RETURN_ON_FALSE(index < rmt_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of the maximum number of leds");
+ uint32_t start = index * rmt_strip->bytes_per_pixel;
+ // In thr order of GRB
+ rmt_strip->buffer[start + 0] = green & 0xFF;
+ rmt_strip->buffer[start + 1] = red & 0xFF;
+ rmt_strip->buffer[start + 2] = blue & 0xFF;
+ if (rmt_strip->bytes_per_pixel > 3) {
+ rmt_strip->buffer[start + 3] = 0;
+ }
+ return ESP_OK;
+}
+
+static esp_err_t led_strip_rmt_refresh(led_strip_t *strip)
+{
+ led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base);
+ ESP_RETURN_ON_ERROR(rmt_write_sample(rmt_strip->rmt_channel, rmt_strip->buffer, rmt_strip->strip_len * rmt_strip->bytes_per_pixel, true), TAG,
+ "transmit RMT samples failed");
+ vTaskDelay(pdMS_TO_TICKS(LED_STRIP_RESET_MS));
+ return ESP_OK;
+}
+
+static esp_err_t led_strip_rmt_clear(led_strip_t *strip)
+{
+ led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base);
+ // Write zero to turn off all LEDs
+ memset(rmt_strip->buffer, 0, rmt_strip->strip_len * rmt_strip->bytes_per_pixel);
+ return led_strip_rmt_refresh(strip);
+}
+
+static esp_err_t led_strip_rmt_del(led_strip_t *strip)
+{
+ led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base);
+ ESP_RETURN_ON_ERROR(rmt_driver_uninstall(rmt_strip->rmt_channel), TAG, "uninstall RMT driver failed");
+ free(rmt_strip);
+ return ESP_OK;
+}
+
+esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const led_strip_rmt_config_t *dev_config, led_strip_handle_t *ret_strip)
+{
+ led_strip_rmt_obj *rmt_strip = NULL;
+ esp_err_t ret = ESP_OK;
+ ESP_RETURN_ON_FALSE(led_config && dev_config && ret_strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+ ESP_RETURN_ON_FALSE(led_config->led_pixel_format < LED_PIXEL_FORMAT_INVALID, ESP_ERR_INVALID_ARG, TAG, "invalid led_pixel_format");
+ ESP_RETURN_ON_FALSE(dev_config->flags.with_dma == 0, ESP_ERR_NOT_SUPPORTED, TAG, "DMA is not supported");
+
+ uint8_t bytes_per_pixel = 3;
+ if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRBW) {
+ bytes_per_pixel = 4;
+ } else if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRB) {
+ bytes_per_pixel = 3;
+ } else {
+ assert(false);
+ }
+
+ // allocate memory for led_strip object
+ rmt_strip = calloc(1, sizeof(led_strip_rmt_obj) + led_config->max_leds * bytes_per_pixel);
+ ESP_RETURN_ON_FALSE(rmt_strip, ESP_ERR_NO_MEM, TAG, "request memory for les_strip failed");
+
+ // install RMT channel driver
+ rmt_config_t config = RMT_DEFAULT_CONFIG_TX(led_config->strip_gpio_num, dev_config->rmt_channel);
+ // set the minimal clock division because the LED strip needs a high clock resolution
+ config.clk_div = 2;
+
+ uint8_t mem_block_num = 2;
+ // override the default value if the user specify the mem block size
+ if (dev_config->mem_block_symbols) {
+ mem_block_num = (dev_config->mem_block_symbols + LED_STRIP_RMT_DEFAULT_MEM_BLOCK_SYMBOLS / 2) / LED_STRIP_RMT_DEFAULT_MEM_BLOCK_SYMBOLS;
+ }
+ config.mem_block_num = mem_block_num;
+
+ ESP_GOTO_ON_ERROR(rmt_config(&config), err, TAG, "RMT config failed");
+ ESP_GOTO_ON_ERROR(rmt_driver_install(config.channel, 0, 0), err, TAG, "RMT install failed");
+
+ uint32_t counter_clk_hz = 0;
+ rmt_get_counter_clock((rmt_channel_t)dev_config->rmt_channel, &counter_clk_hz);
+ // ns -> ticks
+ float ratio = (float)counter_clk_hz / 1e9;
+ if (led_config->led_model == LED_MODEL_WS2812) {
+ led_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS);
+ led_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS);
+ led_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS);
+ led_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS);
+ } else if (led_config->led_model == LED_MODEL_SK6812) {
+ led_t0h_ticks = (uint32_t)(ratio * SK6812_T0H_NS);
+ led_t0l_ticks = (uint32_t)(ratio * SK6812_T0L_NS);
+ led_t1h_ticks = (uint32_t)(ratio * SK6812_T1H_NS);
+ led_t1l_ticks = (uint32_t)(ratio * SK6812_T1L_NS);
+ } else {
+ assert(false);
+ }
+
+ // adapter to translates the LES strip date frame into RMT symbols
+ rmt_translator_init((rmt_channel_t)dev_config->rmt_channel, ws2812_rmt_adapter);
+
+ rmt_strip->bytes_per_pixel = bytes_per_pixel;
+ rmt_strip->rmt_channel = (rmt_channel_t)dev_config->rmt_channel;
+ rmt_strip->strip_len = led_config->max_leds;
+ rmt_strip->base.set_pixel = led_strip_rmt_set_pixel;
+ rmt_strip->base.refresh = led_strip_rmt_refresh;
+ rmt_strip->base.clear = led_strip_rmt_clear;
+ rmt_strip->base.del = led_strip_rmt_del;
+
+ *ret_strip = &rmt_strip->base;
+ return ESP_OK;
+
+err:
+ if (rmt_strip) {
+ free(rmt_strip);
+ }
+ return ret;
+}
diff --git a/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_encoder.c b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_encoder.c
new file mode 100644
index 000000000..d352ac07f
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_encoder.c
@@ -0,0 +1,146 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "esp_check.h"
+#include "led_strip_rmt_encoder.h"
+
+static const char *TAG = "led_rmt_encoder";
+
+typedef struct {
+ rmt_encoder_t base;
+ rmt_encoder_t *bytes_encoder;
+ rmt_encoder_t *copy_encoder;
+ int state;
+ rmt_symbol_word_t reset_code;
+} rmt_led_strip_encoder_t;
+
+static size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
+{
+ rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
+ rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder;
+ rmt_encoder_handle_t copy_encoder = led_encoder->copy_encoder;
+ rmt_encode_state_t session_state = 0;
+ rmt_encode_state_t state = 0;
+ size_t encoded_symbols = 0;
+ switch (led_encoder->state) {
+ case 0: // send RGB data
+ encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, primary_data, data_size, &session_state);
+ if (session_state & RMT_ENCODING_COMPLETE) {
+ led_encoder->state = 1; // switch to next state when current encoding session finished
+ }
+ if (session_state & RMT_ENCODING_MEM_FULL) {
+ state |= RMT_ENCODING_MEM_FULL;
+ goto out; // yield if there's no free space for encoding artifacts
+ }
+ // fall-through
+ case 1: // send reset code
+ encoded_symbols += copy_encoder->encode(copy_encoder, channel, &led_encoder->reset_code,
+ sizeof(led_encoder->reset_code), &session_state);
+ if (session_state & RMT_ENCODING_COMPLETE) {
+ led_encoder->state = 0; // back to the initial encoding session
+ state |= RMT_ENCODING_COMPLETE;
+ }
+ if (session_state & RMT_ENCODING_MEM_FULL) {
+ state |= RMT_ENCODING_MEM_FULL;
+ goto out; // yield if there's no free space for encoding artifacts
+ }
+ }
+out:
+ *ret_state = state;
+ return encoded_symbols;
+}
+
+static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t *encoder)
+{
+ rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
+ rmt_del_encoder(led_encoder->bytes_encoder);
+ rmt_del_encoder(led_encoder->copy_encoder);
+ free(led_encoder);
+ return ESP_OK;
+}
+
+static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t *encoder)
+{
+ rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
+ rmt_encoder_reset(led_encoder->bytes_encoder);
+ rmt_encoder_reset(led_encoder->copy_encoder);
+ led_encoder->state = 0;
+ return ESP_OK;
+}
+
+esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder)
+{
+ esp_err_t ret = ESP_OK;
+ rmt_led_strip_encoder_t *led_encoder = NULL;
+ ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
+ ESP_GOTO_ON_FALSE(config->led_model < LED_MODEL_INVALID, ESP_ERR_INVALID_ARG, err, TAG, "invalid led model");
+ led_encoder = calloc(1, sizeof(rmt_led_strip_encoder_t));
+ ESP_GOTO_ON_FALSE(led_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for led strip encoder");
+ led_encoder->base.encode = rmt_encode_led_strip;
+ led_encoder->base.del = rmt_del_led_strip_encoder;
+ led_encoder->base.reset = rmt_led_strip_encoder_reset;
+ rmt_bytes_encoder_config_t bytes_encoder_config;
+ if (config->led_model == LED_MODEL_SK6812) {
+ bytes_encoder_config = (rmt_bytes_encoder_config_t) {
+ .bit0 = {
+ .level0 = 1,
+ .duration0 = 0.3 * config->resolution / 1000000, // T0H=0.3us
+ .level1 = 0,
+ .duration1 = 0.9 * config->resolution / 1000000, // T0L=0.9us
+ },
+ .bit1 = {
+ .level0 = 1,
+ .duration0 = 0.6 * config->resolution / 1000000, // T1H=0.6us
+ .level1 = 0,
+ .duration1 = 0.6 * config->resolution / 1000000, // T1L=0.6us
+ },
+ .flags.msb_first = 1 // SK6812 transfer bit order: G7...G0R7...R0B7...B0(W7...W0)
+ };
+ } else if (config->led_model == LED_MODEL_WS2812) {
+ // different led strip might have its own timing requirements, following parameter is for WS2812
+ bytes_encoder_config = (rmt_bytes_encoder_config_t) {
+ .bit0 = {
+ .level0 = 1,
+ .duration0 = 0.3 * config->resolution / 1000000, // T0H=0.3us
+ .level1 = 0,
+ .duration1 = 0.9 * config->resolution / 1000000, // T0L=0.9us
+ },
+ .bit1 = {
+ .level0 = 1,
+ .duration0 = 0.9 * config->resolution / 1000000, // T1H=0.9us
+ .level1 = 0,
+ .duration1 = 0.3 * config->resolution / 1000000, // T1L=0.3us
+ },
+ .flags.msb_first = 1 // WS2812 transfer bit order: G7...G0R7...R0B7...B0
+ };
+ } else {
+ assert(false);
+ }
+ ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder(&bytes_encoder_config, &led_encoder->bytes_encoder), err, TAG, "create bytes encoder failed");
+ rmt_copy_encoder_config_t copy_encoder_config = {};
+ ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(©_encoder_config, &led_encoder->copy_encoder), err, TAG, "create copy encoder failed");
+
+ uint32_t reset_ticks = config->resolution / 1000000 * 50 / 2; // reset code duration defaults to 50us
+ led_encoder->reset_code = (rmt_symbol_word_t) {
+ .level0 = 0,
+ .duration0 = reset_ticks,
+ .level1 = 0,
+ .duration1 = reset_ticks,
+ };
+ *ret_encoder = &led_encoder->base;
+ return ESP_OK;
+err:
+ if (led_encoder) {
+ if (led_encoder->bytes_encoder) {
+ rmt_del_encoder(led_encoder->bytes_encoder);
+ }
+ if (led_encoder->copy_encoder) {
+ rmt_del_encoder(led_encoder->copy_encoder);
+ }
+ free(led_encoder);
+ }
+ return ret;
+}
diff --git a/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_encoder.h b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_encoder.h
new file mode 100644
index 000000000..ba71e60ab
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_encoder.h
@@ -0,0 +1,38 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include
+#include "driver/rmt_encoder.h"
+#include "led_strip_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Type of led strip encoder configuration
+ */
+typedef struct {
+ uint32_t resolution; /*!< Encoder resolution, in Hz */
+ led_model_t led_model; /*!< LED model */
+} led_strip_encoder_config_t;
+
+/**
+ * @brief Create RMT encoder for encoding LED strip pixels into RMT symbols
+ *
+ * @param[in] config Encoder configuration
+ * @param[out] ret_encoder Returned encoder handle
+ * @return
+ * - ESP_ERR_INVALID_ARG for any invalid arguments
+ * - ESP_ERR_NO_MEM out of memory when creating led strip encoder
+ * - ESP_OK if creating encoder successfully
+ */
+esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/hw/bsp/espressif/components/led_strip/src/led_strip_spi_dev.c b/hw/bsp/espressif/components/led_strip/src/led_strip_spi_dev.c
new file mode 100644
index 000000000..12ea8fbf3
--- /dev/null
+++ b/hw/bsp/espressif/components/led_strip/src/led_strip_spi_dev.c
@@ -0,0 +1,209 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include
+#include
+#include
+#include "esp_log.h"
+#include "esp_check.h"
+#include "esp_rom_gpio.h"
+#include "soc/spi_periph.h"
+#include "led_strip.h"
+#include "led_strip_interface.h"
+#include "hal/spi_hal.h"
+
+#define LED_STRIP_SPI_DEFAULT_RESOLUTION (2.5 * 1000 * 1000) // 2.5MHz resolution
+#define LED_STRIP_SPI_DEFAULT_TRANS_QUEUE_SIZE 4
+
+#define SPI_BYTES_PER_COLOR_BYTE 3
+#define SPI_BITS_PER_COLOR_BYTE (SPI_BYTES_PER_COLOR_BYTE * 8)
+
+static const char *TAG = "led_strip_spi";
+
+typedef struct {
+ led_strip_t base;
+ spi_host_device_t spi_host;
+ spi_device_handle_t spi_device;
+ uint32_t strip_len;
+ uint8_t bytes_per_pixel;
+ uint8_t pixel_buf[];
+} led_strip_spi_obj;
+
+// please make sure to zero-initialize the buf before calling this function
+static void __led_strip_spi_bit(uint8_t data, uint8_t *buf)
+{
+ // Each color of 1 bit is represented by 3 bits of SPI, low_level:100 ,high_level:110
+ // So a color byte occupies 3 bytes of SPI.
+ *(buf + 2) |= data & BIT(0) ? BIT(2) | BIT(1) : BIT(2);
+ *(buf + 2) |= data & BIT(1) ? BIT(5) | BIT(4) : BIT(5);
+ *(buf + 2) |= data & BIT(2) ? BIT(7) : 0x00;
+ *(buf + 1) |= BIT(0);
+ *(buf + 1) |= data & BIT(3) ? BIT(3) | BIT(2) : BIT(3);
+ *(buf + 1) |= data & BIT(4) ? BIT(6) | BIT(5) : BIT(6);
+ *(buf + 0) |= data & BIT(5) ? BIT(1) | BIT(0) : BIT(1);
+ *(buf + 0) |= data & BIT(6) ? BIT(4) | BIT(3) : BIT(4);
+ *(buf + 0) |= data & BIT(7) ? BIT(7) | BIT(6) : BIT(7);
+}
+
+static esp_err_t led_strip_spi_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue)
+{
+ led_strip_spi_obj *spi_strip = __containerof(strip, led_strip_spi_obj, base);
+ ESP_RETURN_ON_FALSE(index < spi_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of maximum number of LEDs");
+ // LED_PIXEL_FORMAT_GRB takes 72bits(9bytes)
+ uint32_t start = index * spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE;
+ memset(spi_strip->pixel_buf + start, 0, spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE);
+ __led_strip_spi_bit(green, &spi_strip->pixel_buf[start]);
+ __led_strip_spi_bit(red, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE]);
+ __led_strip_spi_bit(blue, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * 2]);
+ if (spi_strip->bytes_per_pixel > 3) {
+ __led_strip_spi_bit(0, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * 3]);
+ }
+ return ESP_OK;
+}
+
+static esp_err_t led_strip_spi_set_pixel_rgbw(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue, uint32_t white)
+{
+ led_strip_spi_obj *spi_strip = __containerof(strip, led_strip_spi_obj, base);
+ ESP_RETURN_ON_FALSE(index < spi_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of maximum number of LEDs");
+ ESP_RETURN_ON_FALSE(spi_strip->bytes_per_pixel == 4, ESP_ERR_INVALID_ARG, TAG, "wrong LED pixel format, expected 4 bytes per pixel");
+ // LED_PIXEL_FORMAT_GRBW takes 96bits(12bytes)
+ uint32_t start = index * spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE;
+ // SK6812 component order is GRBW
+ memset(spi_strip->pixel_buf + start, 0, spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE);
+ __led_strip_spi_bit(green, &spi_strip->pixel_buf[start]);
+ __led_strip_spi_bit(red, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE]);
+ __led_strip_spi_bit(blue, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * 2]);
+ __led_strip_spi_bit(white, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * 3]);
+
+ return ESP_OK;
+}
+
+static esp_err_t led_strip_spi_refresh(led_strip_t *strip)
+{
+ led_strip_spi_obj *spi_strip = __containerof(strip, led_strip_spi_obj, base);
+ spi_transaction_t tx_conf;
+ memset(&tx_conf, 0, sizeof(tx_conf));
+
+ tx_conf.length = spi_strip->strip_len * spi_strip->bytes_per_pixel * SPI_BITS_PER_COLOR_BYTE;
+ tx_conf.tx_buffer = spi_strip->pixel_buf;
+ tx_conf.rx_buffer = NULL;
+ ESP_RETURN_ON_ERROR(spi_device_transmit(spi_strip->spi_device, &tx_conf), TAG, "transmit pixels by SPI failed");
+
+ return ESP_OK;
+}
+
+static esp_err_t led_strip_spi_clear(led_strip_t *strip)
+{
+ led_strip_spi_obj *spi_strip = __containerof(strip, led_strip_spi_obj, base);
+ //Write zero to turn off all leds
+ memset(spi_strip->pixel_buf, 0, spi_strip->strip_len * spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE);
+ uint8_t *buf = spi_strip->pixel_buf;
+ for (int index = 0; index < spi_strip->strip_len * spi_strip->bytes_per_pixel; index++) {
+ __led_strip_spi_bit(0, buf);
+ buf += SPI_BYTES_PER_COLOR_BYTE;
+ }
+
+ return led_strip_spi_refresh(strip);
+}
+
+static esp_err_t led_strip_spi_del(led_strip_t *strip)
+{
+ led_strip_spi_obj *spi_strip = __containerof(strip, led_strip_spi_obj, base);
+
+ ESP_RETURN_ON_ERROR(spi_bus_remove_device(spi_strip->spi_device), TAG, "delete spi device failed");
+ ESP_RETURN_ON_ERROR(spi_bus_free(spi_strip->spi_host), TAG, "free spi bus failed");
+
+ free(spi_strip);
+ return ESP_OK;
+}
+
+esp_err_t led_strip_new_spi_device(const led_strip_config_t *led_config, const led_strip_spi_config_t *spi_config, led_strip_handle_t *ret_strip)
+{
+ led_strip_spi_obj *spi_strip = NULL;
+ esp_err_t ret = ESP_OK;
+ ESP_GOTO_ON_FALSE(led_config && spi_config && ret_strip, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
+ ESP_GOTO_ON_FALSE(led_config->led_pixel_format < LED_PIXEL_FORMAT_INVALID, ESP_ERR_INVALID_ARG, err, TAG, "invalid led_pixel_format");
+ uint8_t bytes_per_pixel = 3;
+ if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRBW) {
+ bytes_per_pixel = 4;
+ } else if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRB) {
+ bytes_per_pixel = 3;
+ } else {
+ assert(false);
+ }
+ uint32_t mem_caps = MALLOC_CAP_DEFAULT;
+ if (spi_config->flags.with_dma) {
+ // DMA buffer must be placed in internal SRAM
+ mem_caps |= MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA;
+ }
+ spi_strip = heap_caps_calloc(1, sizeof(led_strip_spi_obj) + led_config->max_leds * bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE, mem_caps);
+
+ ESP_GOTO_ON_FALSE(spi_strip, ESP_ERR_NO_MEM, err, TAG, "no mem for spi strip");
+
+ spi_strip->spi_host = spi_config->spi_bus;
+ // for backward compatibility, if the user does not set the clk_src, use the default value
+ spi_clock_source_t clk_src = SPI_CLK_SRC_DEFAULT;
+ if (spi_config->clk_src) {
+ clk_src = spi_config->clk_src;
+ }
+
+ spi_bus_config_t spi_bus_cfg = {
+ .mosi_io_num = led_config->strip_gpio_num,
+ //Only use MOSI to generate the signal, set -1 when other pins are not used.
+ .miso_io_num = -1,
+ .sclk_io_num = -1,
+ .quadwp_io_num = -1,
+ .quadhd_io_num = -1,
+ .max_transfer_sz = led_config->max_leds * bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE,
+ };
+ ESP_GOTO_ON_ERROR(spi_bus_initialize(spi_strip->spi_host, &spi_bus_cfg, spi_config->flags.with_dma ? SPI_DMA_CH_AUTO : SPI_DMA_DISABLED), err, TAG, "create SPI bus failed");
+
+ if (led_config->flags.invert_out == true) {
+ esp_rom_gpio_connect_out_signal(led_config->strip_gpio_num, spi_periph_signal[spi_strip->spi_host].spid_out, true, false);
+ }
+
+ spi_device_interface_config_t spi_dev_cfg = {
+ .clock_source = clk_src,
+ .command_bits = 0,
+ .address_bits = 0,
+ .dummy_bits = 0,
+ .clock_speed_hz = LED_STRIP_SPI_DEFAULT_RESOLUTION,
+ .mode = 0,
+ //set -1 when CS is not used
+ .spics_io_num = -1,
+ .queue_size = LED_STRIP_SPI_DEFAULT_TRANS_QUEUE_SIZE,
+ };
+
+ ESP_GOTO_ON_ERROR(spi_bus_add_device(spi_strip->spi_host, &spi_dev_cfg, &spi_strip->spi_device), err, TAG, "Failed to add spi device");
+
+ int clock_resolution_khz = 0;
+ spi_device_get_actual_freq(spi_strip->spi_device, &clock_resolution_khz);
+ // TODO: ideally we should decide the SPI_BYTES_PER_COLOR_BYTE by the real clock resolution
+ // But now, let's fixed the resolution, the downside is, we don't support a clock source whose frequency is not multiple of LED_STRIP_SPI_DEFAULT_RESOLUTION
+ ESP_GOTO_ON_FALSE(clock_resolution_khz == LED_STRIP_SPI_DEFAULT_RESOLUTION / 1000, ESP_ERR_NOT_SUPPORTED, err,
+ TAG, "unsupported clock resolution:%dKHz", clock_resolution_khz);
+
+ spi_strip->bytes_per_pixel = bytes_per_pixel;
+ spi_strip->strip_len = led_config->max_leds;
+ spi_strip->base.set_pixel = led_strip_spi_set_pixel;
+ spi_strip->base.set_pixel_rgbw = led_strip_spi_set_pixel_rgbw;
+ spi_strip->base.refresh = led_strip_spi_refresh;
+ spi_strip->base.clear = led_strip_spi_clear;
+ spi_strip->base.del = led_strip_spi_del;
+
+ *ret_strip = &spi_strip->base;
+ return ESP_OK;
+err:
+ if (spi_strip) {
+ if (spi_strip->spi_device) {
+ spi_bus_remove_device(spi_strip->spi_device);
+ }
+ if (spi_strip->spi_host) {
+ spi_bus_free(spi_strip->spi_host);
+ }
+ free(spi_strip);
+ }
+ return ret;
+}
diff --git a/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt b/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt
new file mode 100644
index 000000000..8bdb3802e
--- /dev/null
+++ b/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt
@@ -0,0 +1,63 @@
+idf_build_get_property(target IDF_TARGET)
+
+set(srcs)
+set(includes_public)
+set(compile_options)
+set(tusb_src "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src")
+
+string(TOUPPER OPT_MCU_${target} tusb_mcu)
+list(APPEND compile_definitions
+ CFG_TUSB_MCU=${tusb_mcu}
+ CFG_TUSB_OS=OPT_OS_FREERTOS
+ )
+
+list(APPEND srcs
+ # common
+ ${tusb_src}/tusb.c
+ ${tusb_src}/common/tusb_fifo.c
+ # device
+ ${tusb_src}/device/usbd.c
+ ${tusb_src}/device/usbd_control.c
+ ${tusb_src}/class/audio/audio_device.c
+ ${tusb_src}/class/cdc/cdc_device.c
+ ${tusb_src}/class/dfu/dfu_device.c
+ ${tusb_src}/class/dfu/dfu_rt_device.c
+ ${tusb_src}/class/hid/hid_device.c
+ ${tusb_src}/class/midi/midi_device.c
+ ${tusb_src}/class/msc/msc_device.c
+ ${tusb_src}/class/net/ecm_rndis_device.c
+ ${tusb_src}/class/net/ncm_device.c
+ ${tusb_src}/class/usbtmc/usbtmc_device.c
+ ${tusb_src}/class/vendor/vendor_device.c
+ ${tusb_src}/class/video/video_device.c
+ ${tusb_src}/portable/synopsys/dwc2/dcd_dwc2.c
+ # host
+ ${tusb_src}/host/usbh.c
+ ${tusb_src}/host/hub.c
+ ${tusb_src}/class/cdc/cdc_host.c
+ ${tusb_src}/class/hid/hid_host.c
+ ${tusb_src}/class/msc/msc_host.c
+ ${tusb_src}/class/vendor/vendor_host.c
+ )
+
+# use max3421 as host controller
+if (MAX3421_HOST STREQUAL "1")
+ list(APPEND srcs ${tusb_src}/portable/analog/max3421/hcd_max3421.c)
+ list(APPEND compile_definitions CFG_TUH_MAX3421=1)
+endif ()
+
+if (DEFINED LOG)
+ list(APPEND compile_definitions CFG_TUSB_DEBUG=${LOG})
+ if (LOG STREQUAL "4")
+ # no inline for debug level 4
+ list(APPEND compile_definitions TU_ATTR_ALWAYS_INLINE=)
+ endif ()
+endif()
+
+idf_component_register(SRCS ${srcs}
+ INCLUDE_DIRS ${tusb_src}
+ REQUIRES src
+ )
+
+target_compile_definitions(${COMPONENT_LIB} PUBLIC ${compile_definitions})
+target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=format)
diff --git a/hw/bsp/espressif/family.cmake b/hw/bsp/espressif/family.cmake
new file mode 100644
index 000000000..eb97401c3
--- /dev/null
+++ b/hw/bsp/espressif/family.cmake
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.5)
+
+# Apply board specific content i.e IDF_TARGET must be set before project.cmake is included
+include("${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake")
+
+string(TOUPPER ${IDF_TARGET} FAMILY_MCUS)
+
+# Add example src and bsp directories
+set(EXTRA_COMPONENT_DIRS "src" "${CMAKE_CURRENT_LIST_DIR}/boards" "${CMAKE_CURRENT_LIST_DIR}/components")
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
diff --git a/hw/bsp/esp32s2/family.mk b/hw/bsp/espressif/family.mk
similarity index 62%
rename from hw/bsp/esp32s2/family.mk
rename to hw/bsp/espressif/family.mk
index b95098e15..0dc21b8eb 100644
--- a/hw/bsp/esp32s2/family.mk
+++ b/hw/bsp/espressif/family.mk
@@ -1,9 +1,21 @@
#DEPS_SUBMODULES +=
+UF2_FAMILY_ID_esp32s2 = 0xbfdd4eee
+UF2_FAMILY_ID_esp32s3 = 0xc47e5767
+
+BOARD_CMAKE := $(file < $(TOP)/$(BOARD_PATH)/board.cmake)
+ifneq ($(findstring esp32s2,$(BOARD_CMAKE)),)
+ IDF_TARGET = esp32s2
+else
+ifneq ($(findstring esp32s3,$(BOARD_CMAKE)),)
+ IDF_TARGET = esp32s3
+endif
+endif
+
.PHONY: all clean flash bootloader-flash app-flash erase monitor dfu-flash dfu
all:
- idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) -DIDF_TARGET=esp32s2 build
+ idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) build
build: all
@@ -17,8 +29,6 @@ clean flash bootloader-flash app-flash erase monitor dfu-flash dfu size size-com
uf2: $(BUILD)/$(PROJECT).uf2
-UF2_FAMILY_ID = 0xbfdd4eee
$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).bin
@echo CREATE $@
- $(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -b 0x0 -c -o $@ $^
-
+ $(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID_$(IDF_TARGET)) -b 0x0 -c -o $@ $^
diff --git a/hw/bsp/f1c100s/README.md b/hw/bsp/f1c100s/README.md
index 4aa1e153b..86d454f8e 100644
--- a/hw/bsp/f1c100s/README.md
+++ b/hw/bsp/f1c100s/README.md
@@ -17,4 +17,4 @@ Flash: `make BOARD=f1c100s flash` will write the image to SPI flash, and then re
## TODO
-* Add F1C100s to `#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT` high speed MCU check in examples (maybe we should extract the logic?)
\ No newline at end of file
+* Add F1C100s to `#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX` high speed MCU check in examples (maybe we should extract the logic?)
diff --git a/hw/bsp/f1c100s/board.h b/hw/bsp/f1c100s/board.h
index 238ac796d..0ef9a1700 100644
--- a/hw/bsp/f1c100s/board.h
+++ b/hw/bsp/f1c100s/board.h
@@ -1 +1 @@
-// Nothing valuable here
\ No newline at end of file
+// Nothing valuable here
diff --git a/hw/bsp/f1c100s/board.mk b/hw/bsp/f1c100s/board.mk
index 5fe26a9ea..3596e5414 100644
--- a/hw/bsp/f1c100s/board.mk
+++ b/hw/bsp/f1c100s/board.mk
@@ -1,5 +1,5 @@
+MCU_DIR = hw/mcu/allwinner/f1c100s
DEPS_SUBMODULES += hw/mcu/allwinner
-
DEFINES += -D__ARM32_ARCH__=5 -D__ARM926EJS__
CFLAGS += \
@@ -18,8 +18,8 @@ CFLAGS += \
$(DEFINES)
LD_FILE = hw/mcu/allwinner/f1c100s/f1c100s.ld
-LDFLAGS += -nostdlib -lgcc
-MCU_DIR = hw/mcu/allwinner/f1c100s
+# TODO may skip nanolib
+LDFLAGS += -nostdlib -lgcc -specs=nosys.specs -specs=nano.specs
SRC_C += \
src/portable/sunxi/dcd_sunxi_musb.c \
@@ -32,7 +32,7 @@ SRC_C += \
$(MCU_DIR)/machine/sys-spi-flash.c \
$(MCU_DIR)/machine/f1c100s-intc.c \
$(MCU_DIR)/lib/malloc.c \
- $(MCU_DIR)/lib/printf.c
+ $(MCU_DIR)/lib/printf.c
SRC_S += \
$(MCU_DIR)/machine/start.S \
@@ -47,6 +47,6 @@ INC += \
flash: flash-xfel
exec: $(BUILD)/$(PROJECT).bin
- xfel ddr
+ xfel ddr
xfel write 0x80000000 $<
- xfel exec 0x80000000
\ No newline at end of file
+ xfel exec 0x80000000
diff --git a/hw/bsp/f1c100s/f1c100s.c b/hw/bsp/f1c100s/f1c100s.c
index d45072ecb..272b756f2 100644
--- a/hw/bsp/f1c100s/f1c100s.c
+++ b/hw/bsp/f1c100s/f1c100s.c
@@ -1,4 +1,4 @@
-/*
+/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@@ -28,7 +28,7 @@
#include
#include
#include
-#include "bsp/board.h"
+#include "bsp/board_api.h"
#include "board.h"
extern void sys_uart_putc(char c);
@@ -125,6 +125,6 @@ static void timer_init(void) {
f1c100s_intc_set_isr(F1C100S_IRQ_TIMER0, timer_handler);
f1c100s_intc_enable_irq(F1C100S_IRQ_TIMER0);
}
-#else
+#else
static void timer_init(void) { }
#endif
diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake
index 601cd54f5..5f0653646 100644
--- a/hw/bsp/family_support.cmake
+++ b/hw/bsp/family_support.cmake
@@ -1,142 +1,520 @@
-if (NOT TARGET _family_support_marker)
- add_library(_family_support_marker INTERFACE)
+include_guard(GLOBAL)
- if (NOT FAMILY)
- message(FATAL_ERROR "You must set a FAMILY variable for the build (e.g. rp2040, eps32s2, esp32s3). You can do this via -DFAMILY=xxx on the cmake command line")
+include(CMakePrintHelpers)
+
+# TOP is path to root directory
+set(TOP "${CMAKE_CURRENT_LIST_DIR}/../..")
+get_filename_component(TOP ${TOP} ABSOLUTE)
+
+#-------------------------------------------------------------
+# Toolchain
+# Can be changed via -DTOOLCHAIN=gcc|iar or -DCMAKE_C_COMPILER=
+#-------------------------------------------------------------
+# Detect toolchain based on CMAKE_C_COMPILER
+if (DEFINED CMAKE_C_COMPILER)
+ string(FIND ${CMAKE_C_COMPILER} "iccarm" IS_IAR)
+ string(FIND ${CMAKE_C_COMPILER} "clang" IS_CLANG)
+ string(FIND ${CMAKE_C_COMPILER} "gcc" IS_GCC)
+
+ if (NOT IS_IAR EQUAL -1)
+ set(TOOLCHAIN iar)
+ elseif (NOT IS_CLANG EQUAL -1)
+ set(TOOLCHAIN clang)
+ elseif (NOT IS_GCC EQUAL -1)
+ set(TOOLCHAIN gcc)
+ endif ()
+endif ()
+
+# default to gcc
+if (NOT DEFINED TOOLCHAIN)
+ set(TOOLCHAIN gcc)
+endif ()
+
+#-------------------------------------------------------------
+# FAMILY and BOARD
+#-------------------------------------------------------------
+if (NOT DEFINED FAMILY)
+ if (NOT DEFINED BOARD)
+ message(FATAL_ERROR "You must set a FAMILY variable for the build (e.g. rp2040, espressif).
+ You can do this via -DFAMILY=xxx on the cmake command line")
+ endif ()
+
+ # Find path contains BOARD
+ file(GLOB BOARD_PATH LIST_DIRECTORIES true
+ RELATIVE ${TOP}/hw/bsp
+ ${TOP}/hw/bsp/*/boards/${BOARD}
+ )
+ if (NOT BOARD_PATH)
+ message(FATAL_ERROR "Could not detect FAMILY from BOARD=${BOARD}")
+ endif ()
+
+ # replace / with ; so that we can get the first element as FAMILY
+ string(REPLACE "/" ";" BOARD_PATH ${BOARD_PATH})
+ list(GET BOARD_PATH 0 FAMILY)
+endif ()
+
+if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/${FAMILY}/family.cmake)
+ message(FATAL_ERROR "Family '${FAMILY}' is not known/supported")
+endif()
+
+if (NOT FAMILY STREQUAL rp2040)
+ # enable LTO if supported skip rp2040
+ include(CheckIPOSupported)
+ check_ipo_supported(RESULT IPO_SUPPORTED)
+ cmake_print_variables(IPO_SUPPORTED)
+ if (IPO_SUPPORTED)
+ set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
+ endif()
+endif()
+
+set(WARNING_FLAGS_GNU
+ -Wall
+ -Wextra
+ -Werror
+ -Wfatal-errors
+ -Wdouble-promotion
+ -Wstrict-prototypes
+ -Wstrict-overflow
+ -Werror-implicit-function-declaration
+ -Wfloat-equal
+ -Wundef
+ -Wshadow
+ -Wwrite-strings
+ -Wsign-compare
+ -Wmissing-format-attribute
+ -Wunreachable-code
+ -Wcast-align
+ -Wcast-function-type
+ -Wcast-qual
+ -Wnull-dereference
+ -Wuninitialized
+ -Wunused
+ -Wreturn-type
+ -Wredundant-decls
+ )
+
+set(WARNING_FLAGS_IAR "")
+
+#-------------------------------------------------------------
+# Functions
+#-------------------------------------------------------------
+
+# Filter example based on only.txt and skip.txt
+function(family_filter RESULT DIR)
+ get_filename_component(DIR ${DIR} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+
+ if (EXISTS "${DIR}/skip.txt")
+ file(STRINGS "${DIR}/skip.txt" SKIPS_LINES)
+ foreach(MCU IN LISTS FAMILY_MCUS)
+ # For each line in only.txt
+ foreach(_line ${SKIPS_LINES})
+ # If mcu:xxx exists for this mcu then skip
+ if (${_line} STREQUAL "mcu:${MCU}" OR ${_line} STREQUAL "board:${BOARD}" OR ${_line} STREQUAL "family:${FAMILY}")
+ set(${RESULT} 0 PARENT_SCOPE)
+ return()
+ endif()
+ endforeach()
+ endforeach()
+ endif ()
+
+ if (EXISTS "${DIR}/only.txt")
+ file(STRINGS "${DIR}/only.txt" ONLYS_LINES)
+ foreach(MCU IN LISTS FAMILY_MCUS)
+ # For each line in only.txt
+ foreach(_line ${ONLYS_LINES})
+ # If mcu:xxx exists for this mcu or board:xxx then include
+ if (${_line} STREQUAL "mcu:${MCU}" OR ${_line} STREQUAL "board:${BOARD}" OR ${_line} STREQUAL "family:${FAMILY}")
+ set(${RESULT} 1 PARENT_SCOPE)
+ return()
+ endif()
+ endforeach()
+ endforeach()
+
+ # Didn't find it in only file so don't build
+ set(${RESULT} 0 PARENT_SCOPE)
+ else()
+ # only.txt not exist so build
+ set(${RESULT} 1 PARENT_SCOPE)
+ endif()
+endfunction()
+
+
+function(family_add_subdirectory DIR)
+ family_filter(SHOULD_ADD "${DIR}")
+ if (SHOULD_ADD)
+ add_subdirectory(${DIR})
+ endif()
+endfunction()
+
+
+function(family_get_project_name OUTPUT_NAME DIR)
+ get_filename_component(SHORT_NAME ${DIR} NAME)
+ set(${OUTPUT_NAME} ${TINYUSB_FAMILY_PROJECT_NAME_PREFIX}${SHORT_NAME} PARENT_SCOPE)
+endfunction()
+
+
+function(family_initialize_project PROJECT DIR)
+ # set output suffix to .elf (skip espressif and rp2040)
+ if(NOT FAMILY STREQUAL "espressif" AND NOT FAMILY STREQUAL "rp2040")
+ set(CMAKE_EXECUTABLE_SUFFIX .elf PARENT_SCOPE)
+ endif()
+
+ family_filter(ALLOWED "${DIR}")
+ if (NOT ALLOWED)
+ get_filename_component(SHORT_NAME ${DIR} NAME)
+ message(FATAL_ERROR "${SHORT_NAME} is not supported on FAMILY=${FAMILY}")
+ endif()
+endfunction()
+
+
+#-------------------------------------------------------------
+# Common Target Configure
+# Most families use these settings except rp2040 and espressif
+#-------------------------------------------------------------
+
+# Add RTOS to example
+function(family_add_rtos TARGET RTOS)
+ if (RTOS STREQUAL "freertos")
+ # freertos config
+ if (NOT TARGET freertos_config)
+ add_library(freertos_config INTERFACE)
+ target_include_directories(freertos_config INTERFACE ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${FAMILY}/FreeRTOSConfig)
+ # add board definition to freertos_config mostly for SystemCoreClock
+ target_link_libraries(freertos_config INTERFACE board_${BOARD})
endif()
- if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/${FAMILY}/family.cmake)
- message(FATAL_ERROR "Family '${FAMILY}' is not known/supported")
+ # freertos kernel
+ if (NOT TARGET freertos_kernel)
+ add_subdirectory(${TOP}/lib/FreeRTOS-Kernel ${CMAKE_BINARY_DIR}/lib/freertos_kernel)
+ endif ()
+
+ target_link_libraries(${TARGET} PUBLIC freertos_kernel)
+ endif ()
+endfunction()
+
+
+# Add common configuration to example
+function(family_configure_common TARGET RTOS)
+ family_add_rtos(${TARGET} ${RTOS})
+
+ string(TOUPPER ${BOARD} BOARD_UPPER)
+ string(REPLACE "-" "_" BOARD_UPPER ${BOARD_UPPER})
+ target_compile_definitions(${TARGET} PUBLIC
+ BOARD_${BOARD_UPPER}
+ )
+
+ # run size after build
+ find_program(SIZE_EXE ${CMAKE_SIZE})
+ if(NOT ${SIZE_EXE} STREQUAL SIZE_EXE-NOTFOUND)
+ add_custom_command(TARGET ${TARGET} POST_BUILD
+ COMMAND ${SIZE_EXE} $
+ )
+ endif ()
+ # Add warnings flags
+ target_compile_options(${TARGET} PUBLIC ${WARNING_FLAGS_${CMAKE_C_COMPILER_ID}})
+
+ # Generate linker map file
+ if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
+ target_link_options(${TARGET} PUBLIC "LINKER:-Map=$.map")
+ if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0)
+ target_link_options(${TARGET} PUBLIC "LINKER:--no-warn-rwx-segments")
+ endif ()
+ elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ target_link_options(${TARGET} PUBLIC "LINKER:-Map=$.map")
+ elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
+ target_link_options(${TARGET} PUBLIC "LINKER:--map=$.map")
+ endif()
+
+ # ETM Trace option
+ if (TRACE_ETM STREQUAL "1")
+ target_compile_definitions(${TARGET} PUBLIC TRACE_ETM)
+ endif ()
+
+ # LOGGER option
+ if (DEFINED LOGGER)
+ target_compile_definitions(${TARGET} PUBLIC LOGGER_${LOGGER})
+
+ # Add segger rtt to example
+ if(LOGGER STREQUAL "RTT" OR LOGGER STREQUAL "rtt")
+ if (NOT TARGET segger_rtt)
+ add_library(segger_rtt STATIC ${TOP}/lib/SEGGER_RTT/RTT/SEGGER_RTT.c)
+ target_include_directories(segger_rtt PUBLIC ${TOP}/lib/SEGGER_RTT/RTT)
+# target_compile_definitions(segger_rtt PUBLIC SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL)
+ endif()
+ target_link_libraries(${TARGET} PUBLIC segger_rtt)
+ endif ()
+ endif ()
+endfunction()
+
+
+# Add tinyusb to example
+function(family_add_tinyusb TARGET OPT_MCU RTOS)
+ # tinyusb target is built for each example since it depends on example's tusb_config.h
+ set(TINYUSB_TARGET_PREFIX ${TARGET}-)
+ add_library(${TARGET}-tinyusb_config INTERFACE)
+
+ # path to tusb_config.h
+ target_include_directories(${TARGET}-tinyusb_config INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src)
+ target_compile_definitions(${TARGET}-tinyusb_config INTERFACE CFG_TUSB_MCU=${OPT_MCU})
+
+ if (DEFINED LOG)
+ target_compile_definitions(${TARGET}-tinyusb_config INTERFACE CFG_TUSB_DEBUG=${LOG})
+ if (LOG STREQUAL "4")
+ # no inline for debug level 4
+ target_compile_definitions(${TARGET}-tinyusb_config INTERFACE TU_ATTR_ALWAYS_INLINE=)
+ endif ()
+ endif()
+
+ if (RTOS STREQUAL "freertos")
+ target_compile_definitions(${TARGET}-tinyusb_config INTERFACE CFG_TUSB_OS=OPT_OS_FREERTOS)
+ endif ()
+
+ # tinyusb's CMakeList.txt
+ add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb)
+
+ if (RTOS STREQUAL "freertos")
+ # link tinyusb with freeRTOS kernel
+ target_link_libraries(${TARGET}-tinyusb PUBLIC freertos_kernel)
+ endif ()
+
+ # use max3421 as host controller
+ if (MAX3421_HOST STREQUAL "1")
+ target_compile_definitions(${TARGET}-tinyusb_config INTERFACE CFG_TUH_MAX3421=1)
+ target_sources(${TARGET}-tinyusb PUBLIC
+ ${TOP}/src/portable/analog/max3421/hcd_max3421.c
+ )
+ endif ()
+
+endfunction()
+
+
+# Add bin/hex output
+function(family_add_bin_hex TARGET)
+ add_custom_command(TARGET ${TARGET} POST_BUILD
+ COMMAND ${CMAKE_OBJCOPY} -Obinary $ $