mirror of
https://github.com/hathach/tinyusb.git
synced 2025-02-06 12:39:54 +00:00
Merge branch 'master' into host-async-control
This commit is contained in:
commit
b5d4c8185d
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -26,4 +26,4 @@ Steps to reproduce the behavior:
|
||||
If applicable, add screenshots, bus capture to help explain your problem.
|
||||
|
||||
**Log**
|
||||
Please provide the stack's log (uart/rtt/swo) where the issue occurred, best with comments to explain the actual events. 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](/examples/readme.md)
|
||||
Please provide the stack's log (uart/rtt/swo) where the issue occurred, best with comments to explain the actual events. 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](/docs/getting_started.md)
|
||||
|
14
.github/workflows/build.yml
vendored
14
.github/workflows/build.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
||||
steps:
|
||||
- name: Setup Ruby
|
||||
uses: actions/setup-ruby@v1
|
||||
|
||||
|
||||
- name: Checkout TinyUSB
|
||||
uses: actions/checkout@v2
|
||||
|
||||
@ -27,6 +27,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
example:
|
||||
- 'device/audio_test'
|
||||
- 'device/board_test'
|
||||
- 'device/cdc_dual_ports'
|
||||
- 'device/cdc_msc'
|
||||
@ -35,13 +36,14 @@ jobs:
|
||||
- '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/usbtmc'
|
||||
- 'device/webusb_serial'
|
||||
- 'host/cdc_msc_hid'
|
||||
|
||||
|
||||
steps:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v1
|
||||
@ -65,21 +67,21 @@ jobs:
|
||||
npm install --global xpm
|
||||
xpm install --global @xpack-dev-tools/arm-none-eabi-gcc@latest
|
||||
xpm install --global @xpack-dev-tools/riscv-none-embed-gcc@latest
|
||||
echo "::add-path::`echo $HOME/opt/xPacks/@xpack-dev-tools/arm-none-eabi-gcc/*/.content/bin`"
|
||||
echo "::add-path::`echo $HOME/opt/xPacks/@xpack-dev-tools/riscv-none-embed-gcc/*/.content/bin`"
|
||||
echo `echo $HOME/opt/xPacks/@xpack-dev-tools/arm-none-eabi-gcc/*/.content/bin` >> $GITHUB_PATH
|
||||
echo `echo $HOME/opt/xPacks/@xpack-dev-tools/riscv-none-embed-gcc/*/.content/bin` >> $GITHUB_PATH
|
||||
|
||||
# TI MSP430 GCC
|
||||
mkdir -p /tmp/dl/
|
||||
[ -f "/tmp/dl/msp430-gcc.tar.bz2" ] || wget --progress=dot:mega $MSP430GCC_URL -O /tmp/dl/msp430-gcc.tar.bz2
|
||||
tar -C $HOME -xaf /tmp/dl/msp430-gcc.tar.bz2
|
||||
echo "::add-path::`echo $HOME/msp430-gcc-*_linux64/bin`"
|
||||
echo `echo $HOME/msp430-gcc-*_linux64/bin` >> $GITHUB_PATH
|
||||
|
||||
- name: Checkout TinyUSB
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# Cannot do submodule checkout here since LWIP's git server cannot checkout unadventised commits (it must use tags)
|
||||
submodules: 'false'
|
||||
|
||||
|
||||
- name: Checkout Submodules
|
||||
run: |
|
||||
git submodule sync --recursive
|
||||
|
@ -4,7 +4,7 @@ The board support code is only used for self-contained examples and testing. It
|
||||
- One LED : for status
|
||||
- One Button : to get input from user
|
||||
- One UART : optional for device, but required for host examples
|
||||
|
||||
|
||||
## Supported Boards
|
||||
|
||||
This code base already had supported for a handful of following boards (sorted alphabetically)
|
||||
@ -28,6 +28,7 @@ This code base already had supported for a handful of following boards (sorted a
|
||||
- [Adafruit ItsyBitsy M4 Express](https://www.adafruit.com/product/3800)
|
||||
- [Adafruit Metro M0 Express](https://www.adafruit.com/product/3505)
|
||||
- [Adafruit Metro M4 Express](https://www.adafruit.com/product/3382)
|
||||
- [D5035-01](https://github.com/RudolphRiedel/USB_CAN-FD)
|
||||
- [Great Scott Gadgets LUNA](https://greatscottgadgets.com/luna/)
|
||||
- [Microchip SAMD11 Xplained](https://www.microchip.com/developmenttools/ProductDetails/atsamd11-xpro)
|
||||
- [Microchip SAMG55 Xplained Pro Evaluation Kit](https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/ATSAMG55-XPRO)
|
||||
@ -114,7 +115,7 @@ This code base already had supported for a handful of following boards (sorted a
|
||||
### TI
|
||||
|
||||
- [MSP430F5529 USB LaunchPad Evaluation Kit](http://www.ti.com/tool/MSP-EXP430F5529LP)
|
||||
|
||||
|
||||
### Tomu
|
||||
|
||||
- [Fomu](https://www.crowdsupply.com/sutajio-kosagi/fomu)
|
||||
|
@ -1,14 +1,6 @@
|
||||
# Getting Started #
|
||||
|
||||
## Get
|
||||
|
||||
```
|
||||
git clone git@github.com:hathach/tinyusb.git tinyusb
|
||||
```
|
||||
|
||||
*examples* is the folder where all the application & project files are located. There are demos for both device and hosts. For each, there are different projects for each of supported RTOS. Click to have more information on how to [build](../examples/readme.md) and run [device](../examples/device/readme.md) demos.
|
||||
|
||||
## Add tinyusb to your project
|
||||
## Add TinyUSB to your project
|
||||
|
||||
It is relatively simple to incorporate tinyusb to your (existing) project
|
||||
|
||||
@ -37,6 +29,104 @@ int main(void)
|
||||
}
|
||||
~~~
|
||||
|
||||
[//]: # "\subpage md_boards_readme"
|
||||
[//]: # "\subpage md_doxygen_started_demo"
|
||||
[//]: # "\subpage md_tools_readme"
|
||||
## Examples
|
||||
|
||||
For your convenience, TinyUSB contains a handful of examples for both host and device with/without RTOS to quickly test the functionality as well as demonstrate how API() should be used. Most examples will work on most of [the supported Boards](boards.md). Firstly we need to `git clone` if not already
|
||||
|
||||
```
|
||||
$ git clone https://github.com/hathach/tinyusb tinyusb
|
||||
$ cd tinyusb
|
||||
```
|
||||
|
||||
TinyUSB examples includes external repos aka submodules to provide low-level MCU peripheral's driver as well as external libraries such as FreeRTOS to compile with. Therefore we will firstly fetch those mcu driver repo by running this command in the top folder repo
|
||||
|
||||
```
|
||||
$ git submodule update --init --recursive
|
||||
```
|
||||
|
||||
It will takes a bit of time due to the number of supported MCUs, luckily we only need to do this once. Or if you only want to test with a specific mcu, you could only fetch its driver submodule.
|
||||
|
||||
### Build
|
||||
|
||||
To build example, first change directory to an example folder.
|
||||
|
||||
```
|
||||
$ cd examples/device/cdc_msc
|
||||
```
|
||||
|
||||
Then compile with `make BOARD=[board_name] all`, for example
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express all
|
||||
```
|
||||
|
||||
#### 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:
|
||||
|
||||
```
|
||||
$ make BOARD=stm32f746disco PORT=1 all
|
||||
```
|
||||
|
||||
#### Port Speed
|
||||
|
||||
A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option `SPEED=full/high` e.g To force F723 operate at full instead of default high speed
|
||||
|
||||
```
|
||||
$ make BOARD=stm32f746disco SPEED=full all
|
||||
```
|
||||
|
||||
### Debug
|
||||
|
||||
To compile for debugging add `DEBUG=1`, for example
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express DEBUG=1 all
|
||||
```
|
||||
|
||||
#### 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.
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 all
|
||||
```
|
||||
|
||||
#### 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:
|
||||
|
||||
- `LOGGER=rtt`: use [Segger RTT protocol](https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/)
|
||||
- Cons: requires jlink as the debugger.
|
||||
- Pros: work with most if not all MCUs
|
||||
- Software viewer is JLink RTT Viewer/Client/Logger which is bundled with JLink driver package.
|
||||
- `LOGGER=swo`: Use dedicated SWO pin of ARM Cortex SWD debug header.
|
||||
- Cons: only work with ARM Cortex MCUs minus M0
|
||||
- Pros: should be compatible with more debugger that support SWO.
|
||||
- Software viewer should be provided along with your debugger driver.
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=rtt all
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=swo all
|
||||
```
|
||||
|
||||
### Flash
|
||||
|
||||
`flash` target will use the default on-board debugger (jlink/cmsisdap/stlink/dfu) to flash the binary, please install those support software in advance. Some board use bootloader/DFU via serial which is required to pass to make command
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express flash
|
||||
$ make SERIAL=/dev/ttyACM0 BOARD=feather_nrf52840_express flash
|
||||
```
|
||||
|
||||
Since jlink can be used with most of the boards, there is also `flash-jlink` target for your convenience.
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express flash-jlink
|
||||
```
|
||||
|
||||
Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can be generated with `uf2` target
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express all uf2
|
||||
```
|
||||
|
0
examples/device/audio_test/.skip.MCU_SAMD11
Normal file
0
examples/device/audio_test/.skip.MCU_SAMD11
Normal file
0
examples/device/audio_test/.skip.MCU_SAME5X
Normal file
0
examples/device/audio_test/.skip.MCU_SAME5X
Normal file
0
examples/device/audio_test/.skip.MCU_SAMG
Normal file
0
examples/device/audio_test/.skip.MCU_SAMG
Normal file
12
examples/device/audio_test/Makefile
Normal file
12
examples/device/audio_test/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
include ../../../tools/top.mk
|
||||
include ../../make.mk
|
||||
|
||||
INC += \
|
||||
src \
|
||||
$(TOP)/hw \
|
||||
|
||||
# Example source
|
||||
EXAMPLE_SOURCE += $(wildcard src/*.c)
|
||||
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
|
||||
|
||||
include ../../rules.mk
|
422
examples/device/audio_test/src/main.c
Normal file
422
examples/device/audio_test/src/main.c
Normal file
@ -0,0 +1,422 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 Reinhard Panhuber
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "tusb.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_N_CHANNELS_TX + 1]; // +1 for master channel 0
|
||||
uint16_t volume[CFG_TUD_AUDIO_N_CHANNELS_TX + 1]; // +1 for master channel 0
|
||||
uint32_t sampFreq;
|
||||
uint8_t clkValid;
|
||||
|
||||
// Range states
|
||||
audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_N_CHANNELS_TX+1]; // Volume range state
|
||||
audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state
|
||||
|
||||
// Audio test data
|
||||
uint16_t test_buffer_audio[CFG_TUD_AUDIO_TX_FIFO_SIZE/2];
|
||||
uint16_t startVal = 0;
|
||||
|
||||
void led_blinking_task(void);
|
||||
void audio_task(void);
|
||||
|
||||
/*------------- MAIN -------------*/
|
||||
int main(void)
|
||||
{
|
||||
board_init();
|
||||
|
||||
tusb_init();
|
||||
|
||||
// Init values
|
||||
sampFreq = 44100;
|
||||
clkValid = 1;
|
||||
|
||||
sampleFreqRng.wNumSubRanges = 1;
|
||||
sampleFreqRng.subrange[0].bMin = 44100;
|
||||
sampleFreqRng.subrange[0].bMax = 44100;
|
||||
sampleFreqRng.subrange[0].bRes = 0;
|
||||
|
||||
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 = BLINK_MOUNTED;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// AUDIO Task
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void audio_task(void)
|
||||
{
|
||||
// Yet to be filled - e.g. put meas data into TX FIFOs etc.
|
||||
asm("nop");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Application Callback API Implementations
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Invoked when audio class specific set request received for an EP
|
||||
bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) pBuff;
|
||||
|
||||
// We do not support any set range requests here, only current value requests
|
||||
TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR);
|
||||
|
||||
// Page 91 in UAC2 specification
|
||||
uint8_t channelNum = TU_U16_LOW(p_request->wValue);
|
||||
uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
|
||||
uint8_t ep = TU_U16_LOW(p_request->wIndex);
|
||||
|
||||
(void) channelNum; (void) ctrlSel; (void) ep;
|
||||
|
||||
return false; // Yet not implemented
|
||||
}
|
||||
|
||||
// Invoked when audio class specific set request received for an interface
|
||||
bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) pBuff;
|
||||
|
||||
// We do not support any set range requests here, only current value requests
|
||||
TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR);
|
||||
|
||||
// Page 91 in UAC2 specification
|
||||
uint8_t channelNum = TU_U16_LOW(p_request->wValue);
|
||||
uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
|
||||
uint8_t itf = TU_U16_LOW(p_request->wIndex);
|
||||
|
||||
(void) channelNum; (void) ctrlSel; (void) itf;
|
||||
|
||||
return false; // Yet not implemented
|
||||
}
|
||||
|
||||
// Invoked when audio class specific set request received for an entity
|
||||
bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
// Page 91 in UAC2 specification
|
||||
uint8_t channelNum = TU_U16_LOW(p_request->wValue);
|
||||
uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
|
||||
uint8_t itf = TU_U16_LOW(p_request->wIndex);
|
||||
uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
|
||||
|
||||
(void) itf;
|
||||
|
||||
// We do not support any set range requests here, only current value requests
|
||||
TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR);
|
||||
|
||||
// If request is for our feature unit
|
||||
if ( entityID == 2 )
|
||||
{
|
||||
switch ( ctrlSel )
|
||||
{
|
||||
case AUDIO_FU_CTRL_MUTE:
|
||||
// Request uses format layout 1
|
||||
TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t));
|
||||
|
||||
mute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur;
|
||||
|
||||
TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum);
|
||||
|
||||
return true;
|
||||
|
||||
case AUDIO_FU_CTRL_VOLUME:
|
||||
// Request uses format layout 2
|
||||
TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t));
|
||||
|
||||
volume[channelNum] = ((audio_control_cur_2_t*) pBuff)->bCur;
|
||||
|
||||
TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum);
|
||||
|
||||
return true;
|
||||
|
||||
// Unknown/Unsupported control
|
||||
default:
|
||||
TU_BREAKPOINT();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false; // Yet not implemented
|
||||
}
|
||||
|
||||
// Invoked when audio class specific get request received for an EP
|
||||
bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
// Page 91 in UAC2 specification
|
||||
uint8_t channelNum = TU_U16_LOW(p_request->wValue);
|
||||
uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
|
||||
uint8_t ep = TU_U16_LOW(p_request->wIndex);
|
||||
|
||||
(void) channelNum; (void) ctrlSel; (void) ep;
|
||||
|
||||
// return 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 == 1)
|
||||
{
|
||||
switch (ctrlSel)
|
||||
{
|
||||
case AUDIO_TE_CTRL_CONNECTOR:;
|
||||
// The terminal connector control only has a get request with only the CUR attribute.
|
||||
|
||||
audio_desc_channel_cluster_t ret;
|
||||
|
||||
// Those are dummy values for now
|
||||
ret.bNrChannels = 1;
|
||||
ret.bmChannelConfig = 0;
|
||||
ret.iChannelNames = 0;
|
||||
|
||||
TU_LOG2(" Get terminal connector\r\n");
|
||||
|
||||
return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*)&ret, sizeof(ret));
|
||||
|
||||
// Unknown/Unsupported control selector
|
||||
default: TU_BREAKPOINT(); return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Feature unit
|
||||
if (entityID == 2)
|
||||
{
|
||||
switch (ctrlSel)
|
||||
{
|
||||
case AUDIO_FU_CTRL_MUTE:
|
||||
// Audio control mute cur parameter block consists of only one byte - we thus can send it right away
|
||||
// There does not exist a range parameter block for mute
|
||||
TU_LOG2(" Get Mute of channel: %u\r\n", channelNum);
|
||||
return tud_control_xfer(rhport, p_request, &mute[channelNum], 1);
|
||||
|
||||
case AUDIO_FU_CTRL_VOLUME:
|
||||
|
||||
switch (p_request->bRequest)
|
||||
{
|
||||
case AUDIO_CS_REQ_CUR:
|
||||
TU_LOG2(" Get Volume of channel: %u\r\n", channelNum);
|
||||
return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum]));
|
||||
case AUDIO_CS_REQ_RANGE:
|
||||
TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum);
|
||||
|
||||
// Copy values - only for testing - better is version below
|
||||
audio_control_range_2_n_t(1) ret;
|
||||
|
||||
ret.wNumSubRanges = 1;
|
||||
ret.subrange[0].bMin = -90; // -90 dB
|
||||
ret.subrange[0].bMax = 90; // +90 dB
|
||||
ret.subrange[0].bRes = 1; // 1 dB steps
|
||||
|
||||
return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*)&ret, sizeof(ret));
|
||||
|
||||
// Unknown/Unsupported control
|
||||
default: TU_BREAKPOINT(); return false;
|
||||
}
|
||||
|
||||
// Unknown/Unsupported control
|
||||
default: TU_BREAKPOINT(); return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Clock Source unit
|
||||
if (entityID == 4)
|
||||
{
|
||||
switch (ctrlSel)
|
||||
{
|
||||
case AUDIO_CS_CTRL_SAM_FREQ:
|
||||
|
||||
// channelNum is always zero in this case
|
||||
|
||||
switch (p_request->bRequest)
|
||||
{
|
||||
case AUDIO_CS_REQ_CUR:
|
||||
TU_LOG2(" Get Sample Freq.\r\n");
|
||||
return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq));
|
||||
case AUDIO_CS_REQ_RANGE:
|
||||
TU_LOG2(" Get Sample Freq. range\r\n");
|
||||
return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng));
|
||||
|
||||
// Unknown/Unsupported control
|
||||
default: TU_BREAKPOINT(); return false;
|
||||
}
|
||||
|
||||
case AUDIO_CS_CTRL_CLK_VALID:
|
||||
// Only cur attribute exists for this request
|
||||
TU_LOG2(" Get Sample Freq. valid\r\n");
|
||||
return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid));
|
||||
|
||||
// Unknown/Unsupported control
|
||||
default: TU_BREAKPOINT(); return false;
|
||||
}
|
||||
}
|
||||
|
||||
TU_LOG2(" Unsupported entity: %d\r\n", entityID);
|
||||
return false; // Yet not implemented
|
||||
}
|
||||
|
||||
bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) itf;
|
||||
(void) ep_in;
|
||||
(void) cur_alt_setting;
|
||||
|
||||
tud_audio_write ((uint8_t *)test_buffer_audio, CFG_TUD_AUDIO_TX_FIFO_SIZE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) n_bytes_copied;
|
||||
(void) itf;
|
||||
(void) ep_in;
|
||||
(void) cur_alt_setting;
|
||||
|
||||
for (size_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_SIZE/2; cnt++)
|
||||
{
|
||||
test_buffer_audio[cnt] = startVal++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) p_request;
|
||||
startVal = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// BLINKING TASK
|
||||
//--------------------------------------------------------------------+
|
||||
void led_blinking_task(void)
|
||||
{
|
||||
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
|
||||
}
|
114
examples/device/audio_test/src/tusb_config.h
Normal file
114
examples/device/audio_test/src/tusb_config.h
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
|
||||
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
|
||||
#else
|
||||
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
|
||||
#endif
|
||||
|
||||
#define CFG_TUSB_OS OPT_OS_NONE
|
||||
|
||||
// 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_CDC 0
|
||||
#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
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Audio format type
|
||||
#define CFG_TUD_AUDIO_USE_TX_FIFO 1
|
||||
#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_I
|
||||
#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED
|
||||
|
||||
// Audio format type I specifications
|
||||
#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM
|
||||
#define CFG_TUD_AUDIO_N_CHANNELS_TX 1
|
||||
#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 2
|
||||
|
||||
// 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_EPSIZE_IN 48*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX*CFG_TUD_AUDIO_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x 1 Channels
|
||||
#define CFG_TUD_AUDIO_TX_FIFO_SIZE 48*2 // 48 Samples (48 kHz) x 2 Bytes/Sample (1/2 word)
|
||||
|
||||
// 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_N_AS_INT 1
|
||||
|
||||
// Size of control request buffer
|
||||
#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64
|
||||
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_CONFIG_H_ */
|
167
examples/device/audio_test/src/usb_descriptors.c
Normal file
167
examples/device/audio_test/src/usb_descriptors.c
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
/* 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 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,
|
||||
|
||||
.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_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
|
||||
#else
|
||||
#define EPNUM_AUDIO 0x01
|
||||
#endif
|
||||
|
||||
// These variables are required by the audio driver in audio_device.c
|
||||
|
||||
// List of audio descriptor lengths which is required by audio driver - you need as many entries as CFG_TUD_AUDIO - unfortunately this is not possible to determine otherwise
|
||||
const uint16_t tud_audio_desc_lengths[] = {TUD_AUDIO_MIC_DESC_LEN};
|
||||
|
||||
// TAKE CARE - THE NUMBER OF AUDIO STREAMING INTERFACES PER AUDIO FUNCTION MUST NOT EXCEED CFG_TUD_AUDIO_N_AS_INT - IF IT DOES INCREASE CFG_TUD_AUDIO_N_AS_INT IN tusb_config.h!
|
||||
|
||||
uint8_t const desc_configuration[] =
|
||||
{
|
||||
// Interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_AUDIO_MIC_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ 3, /*_nBitsUsedPerSample*/ 24, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ 48*4)
|
||||
};
|
||||
|
||||
// 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
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// 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
|
||||
};
|
||||
|
||||
static uint16_t _desc_str[32];
|
||||
|
||||
// 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;
|
||||
|
||||
uint8_t chr_count;
|
||||
|
||||
if ( index == 0)
|
||||
{
|
||||
memcpy(&_desc_str[1], string_desc_arr[0], 2);
|
||||
chr_count = 1;
|
||||
}else
|
||||
{
|
||||
// Convert ASCII string into UTF-16
|
||||
|
||||
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);
|
||||
if ( chr_count > 31 ) chr_count = 31;
|
||||
|
||||
for(uint8_t i=0; i<chr_count; i++)
|
||||
{
|
||||
_desc_str[1+i] = str[i];
|
||||
}
|
||||
}
|
||||
|
||||
// first byte is length (including header), second byte is string type
|
||||
_desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2);
|
||||
|
||||
return _desc_str;
|
||||
}
|
12
examples/device/hid_multiple_interface/Makefile
Normal file
12
examples/device/hid_multiple_interface/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
include ../../../tools/top.mk
|
||||
include ../../make.mk
|
||||
|
||||
INC += \
|
||||
src \
|
||||
$(TOP)/hw \
|
||||
|
||||
# Example source
|
||||
EXAMPLE_SOURCE += $(wildcard src/*.c)
|
||||
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
|
||||
|
||||
include ../../rules.mk
|
207
examples/device/hid_multiple_interface/src/main.c
Normal file
207
examples/device/hid_multiple_interface/src/main.c
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "tusb.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF PROTYPES
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Interface index depends on the order in configuration descriptor
|
||||
enum {
|
||||
ITF_KEYBOARD = 0,
|
||||
ITF_MOUSE = 1
|
||||
};
|
||||
|
||||
/* 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);
|
||||
void hid_task(void);
|
||||
|
||||
/*------------- MAIN -------------*/
|
||||
int main(void)
|
||||
{
|
||||
board_init();
|
||||
tusb_init();
|
||||
|
||||
while (1)
|
||||
{
|
||||
tud_task(); // tinyusb device task
|
||||
led_blinking_task();
|
||||
|
||||
hid_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 = BLINK_MOUNTED;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USB HID
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void hid_task(void)
|
||||
{
|
||||
// Poll every 10ms
|
||||
const uint32_t interval_ms = 10;
|
||||
static uint32_t start_ms = 0;
|
||||
|
||||
if ( board_millis() - start_ms < interval_ms) return; // not enough time
|
||||
start_ms += interval_ms;
|
||||
|
||||
uint32_t const btn = board_button_read();
|
||||
|
||||
// Remote wakeup
|
||||
if ( tud_suspended() && btn )
|
||||
{
|
||||
// Wake up host if we are in suspend mode
|
||||
// and REMOTE_WAKEUP feature is enabled by host
|
||||
tud_remote_wakeup();
|
||||
}
|
||||
|
||||
/*------------- Keyboard -------------*/
|
||||
if ( tud_hid_n_ready(ITF_KEYBOARD) )
|
||||
{
|
||||
// use to avoid send multiple consecutive zero report for keyboard
|
||||
static bool has_key = false;
|
||||
|
||||
if ( btn )
|
||||
{
|
||||
uint8_t keycode[6] = { 0 };
|
||||
keycode[0] = HID_KEY_A;
|
||||
|
||||
tud_hid_n_keyboard_report(ITF_KEYBOARD, 0, 0, keycode);
|
||||
|
||||
has_key = true;
|
||||
}else
|
||||
{
|
||||
// send empty key report if previously has key pressed
|
||||
if (has_key) tud_hid_n_keyboard_report(ITF_KEYBOARD, 0, 0, NULL);
|
||||
has_key = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------- Mouse -------------*/
|
||||
if ( tud_hid_n_ready(ITF_MOUSE) )
|
||||
{
|
||||
if ( btn )
|
||||
{
|
||||
int8_t const delta = 5;
|
||||
|
||||
// no button, right + down, no scroll pan
|
||||
tud_hid_n_mouse_report(ITF_MOUSE, 0, 0x00, delta, delta, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Invoked when received GET_REPORT control request
|
||||
// Application must fill buffer report's content and return its length.
|
||||
// Return zero will cause the stack to STALL request
|
||||
uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
|
||||
{
|
||||
// TODO not Implemented
|
||||
(void) itf;
|
||||
(void) report_id;
|
||||
(void) report_type;
|
||||
(void) buffer;
|
||||
(void) reqlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Invoked when received SET_REPORT control request or
|
||||
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
|
||||
void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
|
||||
{
|
||||
// TODO set LED based on CAPLOCK, NUMLOCK etc...
|
||||
(void) itf;
|
||||
(void) report_id;
|
||||
(void) report_type;
|
||||
(void) buffer;
|
||||
(void) bufsize;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// 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
|
||||
}
|
110
examples/device/hid_multiple_interface/src/tusb_config.h
Normal file
110
examples/device/hid_multiple_interface/src/tusb_config.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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 board.mk
|
||||
#ifndef CFG_TUSB_MCU
|
||||
#error CFG_TUSB_MCU must be defined
|
||||
#endif
|
||||
|
||||
// RHPort number used for device can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_DEVICE_RHPORT_NUM
|
||||
#define BOARD_DEVICE_RHPORT_NUM 0
|
||||
#endif
|
||||
|
||||
// RHPort max operational speed can defined by board.mk
|
||||
// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
|
||||
#ifndef BOARD_DEVICE_RHPORT_SPEED
|
||||
#if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
|
||||
CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56)
|
||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED
|
||||
#else
|
||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Device mode with rhport and speed defined by board.mk
|
||||
#if BOARD_DEVICE_RHPORT_NUM == 0
|
||||
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
|
||||
#elif BOARD_DEVICE_RHPORT_NUM == 1
|
||||
#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
|
||||
#else
|
||||
#error "Incorrect RHPort configuration"
|
||||
#endif
|
||||
|
||||
// This example doesn't use an RTOS
|
||||
#define CFG_TUSB_OS OPT_OS_NONE
|
||||
|
||||
// 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_HID 2
|
||||
#define CFG_TUD_CDC 0
|
||||
#define CFG_TUD_MSC 0
|
||||
#define CFG_TUD_MIDI 0
|
||||
#define CFG_TUD_VENDOR 0
|
||||
|
||||
// HID buffer size Should be sufficient to hold ID (if any) + Data
|
||||
#define CFG_TUD_HID_EP_BUFSIZE 8
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_CONFIG_H_ */
|
188
examples/device/hid_multiple_interface/src/usb_descriptors.c
Normal file
188
examples/device/hid_multiple_interface/src/usb_descriptors.c
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
/* 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] 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(VENDOR, 4) )
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
tusb_desc_device_t const desc_device =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
.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;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// HID Report Descriptor
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
uint8_t const desc_hid_report1[] =
|
||||
{
|
||||
TUD_HID_REPORT_DESC_KEYBOARD()
|
||||
};
|
||||
|
||||
uint8_t const desc_hid_report2[] =
|
||||
{
|
||||
TUD_HID_REPORT_DESC_MOUSE()
|
||||
};
|
||||
|
||||
// Invoked when received GET HID REPORT DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
|
||||
{
|
||||
if (itf == 0)
|
||||
{
|
||||
return desc_hid_report1;
|
||||
}
|
||||
else if (itf == 1)
|
||||
{
|
||||
return desc_hid_report2;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Configuration Descriptor
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
enum
|
||||
{
|
||||
ITF_NUM_HID1,
|
||||
ITF_NUM_HID2,
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN + TUD_HID_DESC_LEN)
|
||||
|
||||
#define EPNUM_HID1 0x81
|
||||
#define EPNUM_HID2 0x82
|
||||
|
||||
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, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
|
||||
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
|
||||
TUD_HID_DESCRIPTOR(ITF_NUM_HID1, 4, HID_PROTOCOL_NONE, sizeof(desc_hid_report1), EPNUM_HID1, CFG_TUD_HID_EP_BUFSIZE, 10),
|
||||
TUD_HID_DESCRIPTOR(ITF_NUM_HID2, 5, HID_PROTOCOL_NONE, sizeof(desc_hid_report2), EPNUM_HID2, CFG_TUD_HID_EP_BUFSIZE, 10)
|
||||
};
|
||||
|
||||
// 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
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// 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
|
||||
"Keyboard Interface", // 4: Interface 1 String
|
||||
"Mouse Interface", // 5: Interface 2 String
|
||||
};
|
||||
|
||||
static uint16_t _desc_str[32];
|
||||
|
||||
// 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;
|
||||
|
||||
uint8_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
|
||||
|
||||
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);
|
||||
if ( chr_count > 31 ) chr_count = 31;
|
||||
|
||||
// Convert ASCII string into UTF-16
|
||||
for(uint8_t i=0; i<chr_count; i++)
|
||||
{
|
||||
_desc_str[1+i] = str[i];
|
||||
}
|
||||
}
|
||||
|
||||
// first byte is length (including header), second byte is string type
|
||||
_desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2);
|
||||
|
||||
return _desc_str;
|
||||
}
|
@ -32,6 +32,16 @@ RNDIS should be valid on Linux and Windows hosts, and CDC-ECM should be valid on
|
||||
|
||||
The MCU appears to the host as IP address 192.168.7.1, and provides a DHCP server, DNS server, and web server.
|
||||
*/
|
||||
/*
|
||||
Some smartphones *may* work with this implementation as well, but likely have limited (broken) drivers,
|
||||
and likely their manufacturer has not tested such functionality. Some code workarounds could be tried:
|
||||
|
||||
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,
|
||||
try changing the first byte of tud_network_mac_address[] below from 0x02 to 0x00 (clearing bit 1).
|
||||
*/
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "tusb.h"
|
||||
@ -50,7 +60,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 two bytes are 0x02,0x02 to indicate a link-local address */
|
||||
/* 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};
|
||||
|
||||
/* network parameters of this MCU */
|
||||
|
@ -1,104 +0,0 @@
|
||||
# Examples
|
||||
|
||||
## Clone this repo
|
||||
|
||||
```
|
||||
$ git clone https://github.com/hathach/tinyusb tinyusb
|
||||
$ cd tinyusb
|
||||
```
|
||||
|
||||
## Fetch submodule MCUs drivers
|
||||
|
||||
TinyUSB examples includes external repos aka submodules to provide low-level MCU peripheral's driver to compile with. Therefore we will firstly fetch those mcu driver repo by running this command in the top folder repo
|
||||
|
||||
```
|
||||
$ git submodule update --init --recursive
|
||||
```
|
||||
|
||||
It will takes a bit of time due to the number of supported MCUs, luckily we only need to do this once. Or if you only want to test with a specific mcu, you could only update its driver submodule
|
||||
|
||||
## Build
|
||||
|
||||
[Here is the list of supported Boards](docs/boards.md) that should work out of the box with provided examples (hopefully).
|
||||
To build example, first change directory to example folder.
|
||||
|
||||
```
|
||||
$ cd examples/device/cdc_msc
|
||||
```
|
||||
|
||||
Then compile with `make BOARD=[your_board] all`, for example
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express all
|
||||
```
|
||||
|
||||
**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:
|
||||
|
||||
```
|
||||
$ make BOARD=stm32f746disco PORT=1 all
|
||||
```
|
||||
|
||||
**Port Speed**
|
||||
|
||||
A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option `SPEED=full/high` e.g To force F723 operate at full instead of default high speed
|
||||
|
||||
```
|
||||
$ make BOARD=stm32f746disco SPEED=full all
|
||||
```
|
||||
|
||||
### Debug
|
||||
|
||||
To compile for debugging with debug symbols add `DEBUG=1`, for example
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express DEBUG=1 all
|
||||
```
|
||||
|
||||
#### 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.
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 all
|
||||
```
|
||||
|
||||
#### 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:
|
||||
|
||||
- `LOGGER=rtt`: use [Segger RTT protocol](https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/)
|
||||
- Cons: requires jlink as the debugger.
|
||||
- Pros: work with most if not all MCUs
|
||||
- Software viewer is JLink RTT Viewer/Client/Logger which is bundled with JLink driver package.
|
||||
- `LOGGER=swo`: Use dedicated SWO pin of ARM Cortex SWD debug header.
|
||||
- Cons: only work with ARM Cortex MCUs minus M0
|
||||
- Pros: should be compatible with more debugger that support SWO.
|
||||
- Software viewer should be provided along with your debugger driver.
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=rtt all
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=swo all
|
||||
```
|
||||
|
||||
## Flash
|
||||
|
||||
`flash` target will use the default on-board debugger (jlink/cmsisdap/stlink/dfu) to flash the binary, please install those support software in advance. Some board use bootloader/DFU via serial which is required to pass to make command
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express flash
|
||||
$ make SERIAL=/dev/ttyACM0 BOARD=feather_nrf52840_express flash
|
||||
```
|
||||
|
||||
Since jlink can be used with most of the boards, there is also `flash-jlink` target for your convenience.
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express flash-jlink
|
||||
```
|
||||
|
||||
Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can be generated with `uf2` target
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express all uf2
|
||||
```
|
@ -33,6 +33,7 @@ SRC_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_rt_device.c \
|
||||
src/class/hid/hid_device.c \
|
||||
@ -147,6 +148,8 @@ else
|
||||
JLINKEXE = JLinkExe
|
||||
endif
|
||||
|
||||
JLINK_IF ?= swd
|
||||
|
||||
# Flash using jlink
|
||||
flash-jlink: $(BUILD)/$(BOARD)-firmware.hex
|
||||
@echo halt > $(BUILD)/$(BOARD).jlink
|
||||
@ -161,4 +164,9 @@ flash-jlink: $(BUILD)/$(BOARD)-firmware.hex
|
||||
flash-stlink: $(BUILD)/$(BOARD)-firmware.elf
|
||||
STM32_Programmer_CLI --connect port=swd --write $< --go
|
||||
|
||||
# flash with pyocd
|
||||
flash-pyocd: $(BUILD)/$(BOARD)-firmware.hex
|
||||
pyocd flash -t $(PYOCD_TARGET) $<
|
||||
pyocd reset -t $(PYOCD_TARGET)
|
||||
|
||||
endif # Make target
|
||||
|
@ -49,7 +49,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = nRF52840_xxAA
|
||||
JLINK_IF = swd
|
||||
|
||||
# For uf2 conversion
|
||||
UF2_FAMILY = 0xADA52840
|
||||
|
@ -51,7 +51,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = nRF52840_xxAA
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using bossac (as part of Nano33 BSP tools)
|
||||
# can be found in arduino15/packages/arduino/tools/bossac/
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020, Ha Thach (tinyusb.org)
|
||||
@ -52,7 +52,8 @@
|
||||
#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
|
||||
#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
|
||||
#include "sam.h"
|
||||
|
||||
#elif CFG_TUSB_MCU == OPT_MCU_SAMG
|
||||
|
@ -49,7 +49,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = nRF52840_xxAA
|
||||
JLINK_IF = swd
|
||||
|
||||
# For uf2 conversion
|
||||
UF2_FAMILY = 0xADA52840
|
||||
|
@ -38,7 +38,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = ATSAMD21G18
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink
|
||||
flash: $(BUILD)/$(BOARD)-firmware.uf2
|
||||
|
62
hw/bsp/d5035_01/board.mk
Normal file
62
hw/bsp/d5035_01/board.mk
Normal file
@ -0,0 +1,62 @@
|
||||
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
|
||||
|
||||
HWREV ?= 1
|
||||
|
||||
CFLAGS += -DHWREV=$(HWREV)
|
||||
|
||||
|
||||
# All source paths should be relative to the top level.
|
||||
LD_FILE = hw/bsp/$(BOARD)/same51j19a_flash.ld
|
||||
|
||||
SRC_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/Core/Include
|
||||
|
||||
# For TinyUSB port source
|
||||
VENDOR = microchip
|
||||
CHIP_FAMILY = samd
|
||||
|
||||
# For freeRTOS port source
|
||||
FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = ATSAME51J19
|
||||
|
||||
# flash using jlink
|
||||
flash: flash-jlink
|
353
hw/bsp/d5035_01/d5035_01.c
Normal file
353
hw/bsp/d5035_01/d5035_01.c
Normal file
@ -0,0 +1,353 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 Jean Gressmann <jean@0x42.de>
|
||||
*
|
||||
* 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 <sam.h>
|
||||
#include "bsp/board.h"
|
||||
|
||||
#include <hal/include/hal_gpio.h>
|
||||
|
||||
#if CONF_CPU_FREQUENCY != 80000000
|
||||
# error "CONF_CPU_FREQUENCY" must 80000000
|
||||
#endif
|
||||
|
||||
#if CONF_GCLK_USB_FREQUENCY != 48000000
|
||||
# error "CONF_GCLK_USB_FREQUENCY" must 48000000
|
||||
#endif
|
||||
|
||||
#if !defined(HWREV)
|
||||
# error Define "HWREV"
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Forward USB interrupt events to TinyUSB IRQ Handler
|
||||
//--------------------------------------------------------------------+
|
||||
void USB_0_Handler (void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
void USB_1_Handler (void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
void USB_2_Handler (void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
void USB_3_Handler (void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
#define LED_PIN PIN_PA02
|
||||
|
||||
#if HWREV < 3
|
||||
# define BOARD_SERCOM SERCOM5
|
||||
#else
|
||||
# define BOARD_SERCOM SERCOM0
|
||||
#endif
|
||||
|
||||
static inline void init_clock(void)
|
||||
{
|
||||
/* AUTOWS is enabled by default in REG_NVMCTRL_CTRLA - no need to change the number of wait states when changing the core clock */
|
||||
#if HWREV == 1
|
||||
/* configure XOSC1 for a 16MHz crystal connected to XIN1/XOUT1 */
|
||||
OSCCTRL->XOSCCTRL[1].reg =
|
||||
OSCCTRL_XOSCCTRL_STARTUP(6) | // 1,953 ms
|
||||
OSCCTRL_XOSCCTRL_RUNSTDBY |
|
||||
OSCCTRL_XOSCCTRL_ENALC |
|
||||
OSCCTRL_XOSCCTRL_IMULT(4) |
|
||||
OSCCTRL_XOSCCTRL_IPTAT(3) |
|
||||
OSCCTRL_XOSCCTRL_XTALEN |
|
||||
OSCCTRL_XOSCCTRL_ENABLE;
|
||||
while(0 == OSCCTRL->STATUS.bit.XOSCRDY1);
|
||||
|
||||
OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(3) | OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC1_Val); /* pre-scaler = 8, input = XOSC1 */
|
||||
OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(39); /* multiply by 40 -> 80 MHz */
|
||||
OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
while(0 == OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL0 to be ready */
|
||||
|
||||
OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(7) | OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC1_Val); /* pre-scaler = 16, input = XOSC1 */
|
||||
OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(47); /* multiply by 48 -> 48 MHz */
|
||||
OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
while(0 == OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL1 to be ready */
|
||||
#else // HWREV >= 1
|
||||
/* configure XOSC0 for a 16MHz crystal connected to XIN0/XOUT0 */
|
||||
OSCCTRL->XOSCCTRL[0].reg =
|
||||
OSCCTRL_XOSCCTRL_STARTUP(6) | // 1,953 ms
|
||||
OSCCTRL_XOSCCTRL_RUNSTDBY |
|
||||
OSCCTRL_XOSCCTRL_ENALC |
|
||||
OSCCTRL_XOSCCTRL_IMULT(4) |
|
||||
OSCCTRL_XOSCCTRL_IPTAT(3) |
|
||||
OSCCTRL_XOSCCTRL_XTALEN |
|
||||
OSCCTRL_XOSCCTRL_ENABLE;
|
||||
while(0 == OSCCTRL->STATUS.bit.XOSCRDY0);
|
||||
|
||||
OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(3) | OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC0_Val); /* pre-scaler = 8, input = XOSC1 */
|
||||
OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(39); /* multiply by 40 -> 80 MHz */
|
||||
OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
while(0 == OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL0 to be ready */
|
||||
|
||||
OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(7) | OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC0_Val); /* pre-scaler = 16, input = XOSC1 */
|
||||
OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(47); /* multiply by 48 -> 48 MHz */
|
||||
OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
while(0 == OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL1 to be ready */
|
||||
#endif // HWREV
|
||||
|
||||
/* configure clock-generator 0 to use DPLL0 as source -> GCLK0 is used for the core */
|
||||
GCLK->GENCTRL[0].reg =
|
||||
GCLK_GENCTRL_DIV(0) |
|
||||
GCLK_GENCTRL_RUNSTDBY |
|
||||
GCLK_GENCTRL_GENEN |
|
||||
GCLK_GENCTRL_SRC_DPLL0 | /* DPLL0 */
|
||||
GCLK_GENCTRL_IDC ;
|
||||
while(1 == GCLK->SYNCBUSY.bit.GENCTRL0); /* wait for the synchronization between clock domains to be complete */
|
||||
|
||||
/* configure clock-generator 1 to use DPLL1 as source -> for use with some peripheral */
|
||||
GCLK->GENCTRL[1].reg =
|
||||
GCLK_GENCTRL_DIV(0) |
|
||||
GCLK_GENCTRL_RUNSTDBY |
|
||||
GCLK_GENCTRL_GENEN |
|
||||
GCLK_GENCTRL_SRC_DPLL1 |
|
||||
GCLK_GENCTRL_IDC ;
|
||||
while(1 == GCLK->SYNCBUSY.bit.GENCTRL1); /* wait for the synchronization between clock domains to be complete */
|
||||
|
||||
/* configure clock-generator 2 to use DPLL0 as source -> for use with SERCOM */
|
||||
GCLK->GENCTRL[2].reg =
|
||||
GCLK_GENCTRL_DIV(1) | /* 80MHz */
|
||||
GCLK_GENCTRL_RUNSTDBY |
|
||||
GCLK_GENCTRL_GENEN |
|
||||
GCLK_GENCTRL_SRC_DPLL0 |
|
||||
GCLK_GENCTRL_IDC ;
|
||||
while(1 == GCLK->SYNCBUSY.bit.GENCTRL2); /* wait for the synchronization between clock domains to be complete */
|
||||
}
|
||||
|
||||
static inline void uart_init(void)
|
||||
{
|
||||
#if HWREV < 3
|
||||
/* configure SERCOM5 on PB02 */
|
||||
PORT->Group[1].WRCONFIG.reg =
|
||||
PORT_WRCONFIG_WRPINCFG |
|
||||
PORT_WRCONFIG_WRPMUX |
|
||||
PORT_WRCONFIG_PMUX(3) | /* function D */
|
||||
PORT_WRCONFIG_DRVSTR |
|
||||
PORT_WRCONFIG_PINMASK(0x0004) | /* PB02 */
|
||||
PORT_WRCONFIG_PMUXEN;
|
||||
|
||||
MCLK->APBDMASK.bit.SERCOM5_ = 1;
|
||||
GCLK->PCHCTRL[SERCOM5_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK2 | GCLK_PCHCTRL_CHEN; /* setup SERCOM to use GLCK2 -> 80MHz */
|
||||
|
||||
SERCOM5->USART.CTRLA.reg = 0x00; /* disable SERCOM -> enable config */
|
||||
while(SERCOM5->USART.SYNCBUSY.bit.ENABLE);
|
||||
|
||||
SERCOM5->USART.CTRLA.reg = /* CMODE = 0 -> async, SAMPA = 0, FORM = 0 -> USART frame, SMPR = 0 -> arithmetic baud rate */
|
||||
SERCOM_USART_CTRLA_SAMPR(1) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */
|
||||
// SERCOM_USART_CTRLA_FORM(0) | /* 0 = USART Frame, 2 = LIN Master */
|
||||
SERCOM_USART_CTRLA_DORD | /* LSB first */
|
||||
SERCOM_USART_CTRLA_MODE(1) | /* 0 = Asynchronous, 1 = USART with internal clock */
|
||||
SERCOM_USART_CTRLA_RXPO(1) | /* SERCOM PAD[1] is used for data reception */
|
||||
SERCOM_USART_CTRLA_TXPO(0); /* SERCOM PAD[0] is used for data transmission */
|
||||
|
||||
SERCOM5->USART.CTRLB.reg = /* RXEM = 0 -> receiver disabled, LINCMD = 0 -> normal USART transmission, SFDE = 0 -> start-of-frame detection disabled, SBMODE = 0 -> one stop bit, CHSIZE = 0 -> 8 bits */
|
||||
SERCOM_USART_CTRLB_TXEN; /* transmitter enabled */
|
||||
SERCOM5->USART.CTRLC.reg = 0x00;
|
||||
// 21.701388889 @ baud rate of 230400 bit/s, table 33-2, p 918 of DS60001507E
|
||||
SERCOM5->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(7) | SERCOM_USART_BAUD_FRAC_BAUD(21);
|
||||
|
||||
// SERCOM5->USART.INTENSET.reg = SERCOM_USART_INTENSET_TXC;
|
||||
SERCOM5->SPI.CTRLA.bit.ENABLE = 1; /* activate SERCOM */
|
||||
while(SERCOM5->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */
|
||||
#else
|
||||
/* configure SERCOM0 on PA08 */
|
||||
PORT->Group[0].WRCONFIG.reg =
|
||||
PORT_WRCONFIG_WRPINCFG |
|
||||
PORT_WRCONFIG_WRPMUX |
|
||||
PORT_WRCONFIG_PMUX(2) | /* function C */
|
||||
PORT_WRCONFIG_DRVSTR |
|
||||
PORT_WRCONFIG_PINMASK(0x0100) | /* PA08 */
|
||||
PORT_WRCONFIG_PMUXEN;
|
||||
|
||||
MCLK->APBAMASK.bit.SERCOM0_ = 1;
|
||||
GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK2 | GCLK_PCHCTRL_CHEN; /* setup SERCOM to use GLCK2 -> 80MHz */
|
||||
|
||||
SERCOM0->USART.CTRLA.reg = 0x00; /* disable SERCOM -> enable config */
|
||||
while(SERCOM0->USART.SYNCBUSY.bit.ENABLE);
|
||||
|
||||
SERCOM0->USART.CTRLA.reg = /* CMODE = 0 -> async, SAMPA = 0, FORM = 0 -> USART frame, SMPR = 0 -> arithmetic baud rate */
|
||||
SERCOM_USART_CTRLA_SAMPR(1) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */
|
||||
// SERCOM_USART_CTRLA_FORM(0) | /* 0 = USART Frame, 2 = LIN Master */
|
||||
SERCOM_USART_CTRLA_DORD | /* LSB first */
|
||||
SERCOM_USART_CTRLA_MODE(1) | /* 0 = Asynchronous, 1 = USART with internal clock */
|
||||
SERCOM_USART_CTRLA_RXPO(1) | /* SERCOM PAD[1] is used for data reception */
|
||||
SERCOM_USART_CTRLA_TXPO(0); /* SERCOM PAD[0] is used for data transmission */
|
||||
|
||||
SERCOM0->USART.CTRLB.reg = /* RXEM = 0 -> receiver disabled, LINCMD = 0 -> normal USART transmission, SFDE = 0 -> start-of-frame detection disabled, SBMODE = 0 -> one stop bit, CHSIZE = 0 -> 8 bits */
|
||||
SERCOM_USART_CTRLB_TXEN; /* transmitter enabled */
|
||||
SERCOM0->USART.CTRLC.reg = 0x00;
|
||||
// 21.701388889 @ baud rate of 230400 bit/s, table 33-2, p 918 of DS60001507E
|
||||
SERCOM0->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(7) | SERCOM_USART_BAUD_FRAC_BAUD(21);
|
||||
|
||||
// SERCOM0->USART.INTENSET.reg = SERCOM_USART_INTENSET_TXC;
|
||||
SERCOM0->SPI.CTRLA.bit.ENABLE = 1; /* activate SERCOM */
|
||||
while(SERCOM0->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void uart_send_buffer(uint8_t const *text, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
BOARD_SERCOM->USART.DATA.reg = text[i];
|
||||
while((BOARD_SERCOM->USART.INTFLAG.reg & SERCOM_SPI_INTFLAG_TXC) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void uart_send_str(const char* text)
|
||||
{
|
||||
while (*text) {
|
||||
BOARD_SERCOM->USART.DATA.reg = *text++;
|
||||
while((BOARD_SERCOM->USART.INTFLAG.reg & SERCOM_SPI_INTFLAG_TXC) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void board_init(void)
|
||||
{
|
||||
init_clock();
|
||||
|
||||
SystemCoreClock = CONF_CPU_FREQUENCY;
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_NONE
|
||||
SysTick_Config(CONF_CPU_FREQUENCY / 1000);
|
||||
#endif
|
||||
|
||||
uart_init();
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
uart_send_str(BOARD_NAME " UART initialized\n");
|
||||
tu_printf(BOARD_NAME " reset cause %#02x\n", RSTC->RCAUSE.reg);
|
||||
#endif
|
||||
|
||||
// Led init
|
||||
gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(LED_PIN, 0);
|
||||
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
uart_send_str(BOARD_NAME " LED pin configured\n");
|
||||
#endif
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_FREERTOS
|
||||
// If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
|
||||
NVIC_SetPriority(USB_0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
|
||||
NVIC_SetPriority(USB_1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
|
||||
NVIC_SetPriority(USB_2_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
|
||||
NVIC_SetPriority(USB_3_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
|
||||
#endif
|
||||
|
||||
|
||||
#if TUSB_OPT_DEVICE_ENABLED
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
uart_send_str(BOARD_NAME " USB device enabled\n");
|
||||
#endif
|
||||
|
||||
/* USB clock init
|
||||
* The USB module requires a GCLK_USB of 48 MHz ~ 0.25% clock
|
||||
* for low speed and full speed operation. */
|
||||
hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN);
|
||||
hri_mclk_set_AHBMASK_USB_bit(MCLK);
|
||||
hri_mclk_set_APBBMASK_USB_bit(MCLK);
|
||||
|
||||
// USB pin init
|
||||
gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(PIN_PA24, false);
|
||||
gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF);
|
||||
gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(PIN_PA25, false);
|
||||
gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF);
|
||||
|
||||
gpio_set_pin_function(PIN_PA24, PINMUX_PA24H_USB_DM);
|
||||
gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP);
|
||||
|
||||
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
uart_send_str(BOARD_NAME " USB device configured\n");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Board porting API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void board_led_write(bool state)
|
||||
{
|
||||
gpio_set_pin_level(LED_PIN, state);
|
||||
}
|
||||
|
||||
uint32_t board_button_read(void)
|
||||
{
|
||||
// this board has no button
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_uart_read(uint8_t* buf, int len)
|
||||
{
|
||||
(void) buf; (void) len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_uart_write(void const * buf, int len)
|
||||
{
|
||||
if (len < 0) {
|
||||
uart_send_str(buf);
|
||||
} else {
|
||||
uart_send_buffer(buf, len);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
// Required by __libc_init_array in startup code if we are compiling using
|
||||
// -nostdlib/-nostartfiles.
|
||||
void _init(void)
|
||||
{
|
||||
|
||||
}
|
163
hw/bsp/d5035_01/same51j19a_flash.ld
Normal file
163
hw/bsp/d5035_01/same51j19a_flash.ld
Normal file
@ -0,0 +1,163 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Linker script for running in internal FLASH on the SAME51J19A
|
||||
*
|
||||
* Copyright (c) 2019 Microchip Technology Inc.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the Licence 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.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
SEARCH_DIR(.)
|
||||
|
||||
/* Memory Spaces Definitions */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
|
||||
bkupram (rwx) : ORIGIN = 0x47000000, LENGTH = 0x00002000
|
||||
qspi (rwx) : ORIGIN = 0x04000000, LENGTH = 0x01000000
|
||||
}
|
||||
|
||||
/* The stack size used by the application. NOTE: you need to adjust according to your application. */
|
||||
STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x1000;
|
||||
|
||||
/* Section Definitions */
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sfixed = .;
|
||||
KEEP(*(.vectors .vectors.*))
|
||||
*(.text .text.* .gnu.linkonce.t.*)
|
||||
*(.glue_7t) *(.glue_7)
|
||||
*(.rodata .rodata* .gnu.linkonce.r.*)
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
|
||||
/* Support C constructors, and C destructors in both user code
|
||||
and the C library. This also provides support for C++ code. */
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.init))
|
||||
. = ALIGN(4);
|
||||
__preinit_array_start = .;
|
||||
KEEP (*(.preinit_array))
|
||||
__preinit_array_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
__init_array_start = .;
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
__init_array_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*crtend.o(.ctors))
|
||||
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.fini))
|
||||
|
||||
. = ALIGN(4);
|
||||
__fini_array_start = .;
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
__fini_array_end = .;
|
||||
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*crtend.o(.dtors))
|
||||
|
||||
. = ALIGN(4);
|
||||
_efixed = .; /* End of text section */
|
||||
} > rom
|
||||
|
||||
/* .ARM.exidx is sorted, so has to go in its own output section. */
|
||||
PROVIDE_HIDDEN (__exidx_start = .);
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > rom
|
||||
PROVIDE_HIDDEN (__exidx_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
|
||||
.relocate : AT (_etext)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_srelocate = .;
|
||||
*(.ramfunc .ramfunc.*);
|
||||
*(.data .data.*);
|
||||
. = ALIGN(4);
|
||||
_erelocate = .;
|
||||
} > ram
|
||||
|
||||
.bkupram (NOLOAD):
|
||||
{
|
||||
. = ALIGN(8);
|
||||
_sbkupram = .;
|
||||
*(.bkupram .bkupram.*);
|
||||
. = ALIGN(8);
|
||||
_ebkupram = .;
|
||||
} > bkupram
|
||||
|
||||
.qspi (NOLOAD):
|
||||
{
|
||||
. = ALIGN(8);
|
||||
_sqspi = .;
|
||||
*(.qspi .qspi.*);
|
||||
. = ALIGN(8);
|
||||
_eqspi = .;
|
||||
} > qspi
|
||||
|
||||
/* .bss section which is used for uninitialized data */
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sbss = . ;
|
||||
_szero = .;
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_ebss = . ;
|
||||
_ezero = .;
|
||||
} > ram
|
||||
|
||||
/* stack section */
|
||||
.stack (NOLOAD):
|
||||
{
|
||||
. = ALIGN(8);
|
||||
_sstack = .;
|
||||
. = . + STACK_SIZE;
|
||||
. = ALIGN(8);
|
||||
_estack = .;
|
||||
} > ram
|
||||
|
||||
. = ALIGN(4);
|
||||
_end = . ;
|
||||
}
|
@ -38,7 +38,6 @@ FREERTOS_PORT = ARM_CM33_NTZ/non_secure
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = DA14695
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink but with some twists
|
||||
flash: flash-dialog
|
||||
|
@ -38,7 +38,6 @@ FREERTOS_PORT = ARM_CM33_NTZ/non_secure
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = DA14699
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink but with some twists
|
||||
flash: flash-dialog
|
||||
|
@ -42,7 +42,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = LPC4088
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink
|
||||
flash: flash-jlink
|
||||
|
@ -42,7 +42,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = LPC4357_M4
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink
|
||||
flash: flash-jlink
|
||||
|
@ -25,11 +25,11 @@
|
||||
*/
|
||||
|
||||
#include "../board.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#include "hal/usb_hal.h"
|
||||
#include "soc/usb_periph.h"
|
||||
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "driver/rmt.h"
|
||||
#include "led_strip/include/led_strip.h"
|
||||
|
||||
@ -38,11 +38,10 @@
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#define LED_PIN 45
|
||||
|
||||
#define BUTTON_PIN 0
|
||||
#define BUTTON_STATE_ACTIVE 0
|
||||
|
||||
|
||||
static void configure_pins(usb_hal_context_t *usb);
|
||||
static led_strip_t *strip;
|
||||
|
||||
// Initialize on-board peripherals : led, button, uart and USB
|
||||
@ -72,10 +71,33 @@ void board_init(void)
|
||||
.use_external_phy = false // use built-in PHY
|
||||
};
|
||||
usb_hal_init(&hal);
|
||||
configure_pins(&hal);
|
||||
}
|
||||
|
||||
// Pin drive strength
|
||||
gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3);
|
||||
gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3);
|
||||
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 ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) {
|
||||
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
|
||||
|
@ -25,11 +25,12 @@
|
||||
*/
|
||||
|
||||
#include "../board.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#include "hal/usb_hal.h"
|
||||
#include "soc/usb_periph.h"
|
||||
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "driver/rmt.h"
|
||||
#include "led_strip/include/led_strip.h"
|
||||
|
||||
@ -41,11 +42,10 @@
|
||||
// however earlier revision v1.1 WS2812 is connected to GPIO 17
|
||||
//#define LED_PIN 17 // v1.1
|
||||
#define LED_PIN 18 // v1.2 and later
|
||||
|
||||
#define BUTTON_PIN 0
|
||||
#define BUTTON_STATE_ACTIVE 0
|
||||
|
||||
|
||||
static void configure_pins(usb_hal_context_t *usb);
|
||||
static led_strip_t *strip;
|
||||
|
||||
// Initialize on-board peripherals : led, button, uart and USB
|
||||
@ -75,10 +75,33 @@ void board_init(void)
|
||||
.use_external_phy = false // use built-in PHY
|
||||
};
|
||||
usb_hal_init(&hal);
|
||||
configure_pins(&hal);
|
||||
}
|
||||
|
||||
// Pin drive strength
|
||||
gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3);
|
||||
gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3);
|
||||
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 ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) {
|
||||
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
|
||||
|
@ -39,7 +39,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = ATSAMD21G18
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using bossac at least version 1.8
|
||||
# can be found in arduino15/packages/arduino/tools/bossac/
|
||||
|
@ -42,7 +42,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = ATSAMD51J19
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using bossac at least version 1.8
|
||||
# can be found in arduino15/packages/arduino/tools/bossac/
|
||||
|
@ -50,7 +50,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = nRF52840_xxAA
|
||||
JLINK_IF = swd
|
||||
|
||||
# For uf2 conversion
|
||||
UF2_FAMILY = 0xADA52840
|
||||
|
@ -49,7 +49,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = nRF52840_xxAA
|
||||
JLINK_IF = swd
|
||||
|
||||
# For uf2 conversion
|
||||
UF2_FAMILY = 0xADA52840
|
||||
|
@ -44,7 +44,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32f405rg
|
||||
JLINK_IF = swd
|
||||
|
||||
# Path to STM32 Cube Programmer CLI, should be added into system path
|
||||
STM32Prog = STM32_Programmer_CLI
|
||||
|
@ -39,7 +39,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = ATSAMD21G18
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using bossac at least version 1.8
|
||||
# can be found in arduino15/packages/arduino/tools/bossac/
|
||||
|
@ -42,7 +42,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = ATSAMD51J19
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using bossac at least version 1.8
|
||||
# can be found in arduino15/packages/arduino/tools/bossac/
|
||||
|
@ -50,7 +50,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = nRF52840_xxAA
|
||||
JLINK_IF = swd
|
||||
|
||||
# For uf2 conversion
|
||||
UF2_FAMILY = 0xADA52840
|
||||
|
@ -40,7 +40,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = LPC11U37/401
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using pyocd
|
||||
flash: $(BUILD)/$(BOARD)-firmware.hex
|
||||
|
@ -37,7 +37,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = LPC11U68
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using pyocd
|
||||
flash: $(BUILD)/$(BOARD)-firmware.hex
|
||||
|
@ -40,7 +40,6 @@ FREERTOS_PORT = ARM_CM3
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = LPC1347
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink
|
||||
flash: flash-jlink
|
||||
|
@ -40,7 +40,6 @@ FREERTOS_PORT = ARM_CM3
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = LPC1549
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink
|
||||
flash: flash-jlink
|
||||
|
@ -39,7 +39,6 @@ FREERTOS_PORT = ARM_CM3
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = LPC1769
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink
|
||||
flash: flash-jlink
|
||||
|
@ -41,7 +41,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = LPC51U68
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using pyocd (51u68 is not supported yet)
|
||||
flash: $(BUILD)/$(BOARD)-firmware.hex
|
||||
|
@ -43,7 +43,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = LPC54114J256_M4
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using pyocd
|
||||
flash: $(BUILD)/$(BOARD)-firmware.hex
|
||||
|
@ -43,7 +43,6 @@ FREERTOS_PORT = ARM_CM33_NTZ/non_secure
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = LPC55S69
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using pyocd
|
||||
flash: $(BUILD)/$(BOARD)-firmware.hex
|
||||
|
@ -39,7 +39,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = ATSAMD21G18
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink
|
||||
flash: $(BUILD)/$(BOARD)-firmware.bin
|
||||
|
@ -39,7 +39,6 @@ FREERTOS_PORT = ARM_CM3
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = LPC1768
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using pyocd
|
||||
flash: $(BUILD)/$(BOARD)-firmware.hex
|
||||
|
@ -37,7 +37,6 @@ FREERTOS_PORT = ARM_CM3
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = LPC1857
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink
|
||||
flash: flash-jlink
|
||||
|
@ -39,7 +39,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = ATSAMD21G18
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using bossac at least version 1.8
|
||||
# can be found in arduino15/packages/arduino/tools/bossac/
|
||||
|
@ -42,7 +42,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = ATSAMD51J19
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using bossac at least version 1.8
|
||||
# can be found in arduino15/packages/arduino/tools/bossac/
|
||||
|
@ -19,6 +19,9 @@ MCU_DIR = hw/mcu/nxp/sdk/devices/MIMXRT1011
|
||||
# All source paths should be relative to the top level.
|
||||
LD_FILE = $(MCU_DIR)/gcc/MIMXRT1011xxxxx_flexspi_nor.ld
|
||||
|
||||
LDFLAGS += \
|
||||
-Wl,--defsym,__stack_size__=0x800 \
|
||||
|
||||
SRC_C += \
|
||||
$(MCU_DIR)/system_MIMXRT1011.c \
|
||||
$(MCU_DIR)/xip/fsl_flexspi_nor_boot.c \
|
||||
@ -46,8 +49,9 @@ FREERTOS_PORT = ARM_CM7/r0p1
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = MIMXRT1011DAE5A
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash by copying bin file to DAP Mass Storage
|
||||
flash: $(BUILD)/$(BOARD)-firmware.bin
|
||||
cp $< /media/$(USER)/RT1010-EVK/
|
||||
# For flash-pyocd target
|
||||
PYOCD_TARGET = mimxrt1010
|
||||
|
||||
# flash using pyocd
|
||||
flash: flash-pyocd
|
||||
|
@ -45,12 +45,9 @@ FREERTOS_PORT = ARM_CM7/r0p1
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = MIMXRT1015DAF5A
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash by copying bin file to DAP Mass Storage
|
||||
flash: $(BUILD)/$(BOARD)-firmware.bin
|
||||
cp $< /media/$(USER)/RT1015-EVK/
|
||||
# For flash-pyocd target
|
||||
PYOCD_TARGET = mimxrt1015
|
||||
|
||||
# flash using pyocd
|
||||
#flash: $(BUILD)/$(BOARD)-firmware.hex
|
||||
# pyocd flash -b MIMXRT1015-EVK $<
|
||||
flash: flash-pyocd
|
||||
|
@ -45,8 +45,9 @@ FREERTOS_PORT = ARM_CM7/r0p1
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = MIMXRT1021DAG5A
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash by copying bin file to DAP Mass Storage
|
||||
flash: $(BUILD)/$(BOARD)-firmware.bin
|
||||
cp $< /media/$(USER)/RT1020-EVK/
|
||||
# For flash-pyocd target
|
||||
PYOCD_TARGET = mimxrt1020
|
||||
|
||||
# flash using pyocd
|
||||
flash: flash-pyocd
|
||||
|
@ -43,10 +43,8 @@ CHIP_FAMILY = transdimension
|
||||
# For freeRTOS port source
|
||||
FREERTOS_PORT = ARM_CM7/r0p1
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = MIMXRT1052xxx6B
|
||||
JLINK_IF = swd
|
||||
# For flash-pyocd target
|
||||
PYOCD_TARGET = mimxrt1050
|
||||
|
||||
# flash by copying bin file to DAP Mass Storage
|
||||
flash: $(BUILD)/$(BOARD)-firmware.bin
|
||||
cp $< /media/$(USER)/RT1050-EVK/
|
||||
# flash using pyocd
|
||||
flash: flash-pyocd
|
||||
|
@ -45,8 +45,9 @@ FREERTOS_PORT = ARM_CM7/r0p1
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = MIMXRT1062xxx6A
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash by copying bin file to DAP Mass Storage
|
||||
flash: $(BUILD)/$(BOARD)-firmware.bin
|
||||
cp $< /media/$(USER)/RT1060-EVK/
|
||||
# For flash-pyocd target
|
||||
PYOCD_TARGET = mimxrt1060
|
||||
|
||||
# flash using pyocd
|
||||
flash: flash-pyocd
|
||||
|
@ -45,8 +45,9 @@ FREERTOS_PORT = ARM_CM7/r0p1
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = MIMXRT1064xxx6A
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash by copying bin file to DAP Mass Storage
|
||||
flash: $(BUILD)/$(BOARD)-firmware.bin
|
||||
cp $< /media/$(USER)/RT1064-EVK/
|
||||
# For flash-pyocd target
|
||||
PYOCD_TARGET = mimxrt1064
|
||||
|
||||
# flash using pyocd
|
||||
flash: flash-pyocd
|
||||
|
@ -48,7 +48,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = nRF52840_xxAA
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using Nordic nrfutil (pip2 install nrfutil)
|
||||
# make BOARD=nrf52840_mdk_dongle SERIAL=/dev/ttyACM0 all flash
|
||||
|
@ -49,7 +49,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = NUC121SC2AE
|
||||
JLINK_IF = swd
|
||||
|
||||
# Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton
|
||||
# Please compile and install it from github source
|
||||
|
@ -33,7 +33,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = NUC125SC2AE
|
||||
JLINK_IF = swd
|
||||
|
||||
# Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton
|
||||
# Please compile and install it from github source
|
||||
|
@ -53,7 +53,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = NUC126VG4AE
|
||||
JLINK_IF = swd
|
||||
|
||||
# Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton
|
||||
# Please compile and install it from github source
|
||||
|
@ -49,7 +49,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = NUC120LE3
|
||||
JLINK_IF = swd
|
||||
|
||||
# Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton
|
||||
# Please compile and install it from github source
|
||||
|
@ -44,7 +44,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = NUC505YO13Y
|
||||
JLINK_IF = swd
|
||||
|
||||
# Note
|
||||
# To be able to program the SPI flash, it need to boot with ICP mode "1011".
|
||||
|
@ -50,7 +50,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = nRF52840_xxAA
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink
|
||||
flash: flash-jlink
|
||||
|
@ -49,7 +49,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = nRF52840_xxAA
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using Nordic nrfutil (pip2 install nrfutil)
|
||||
# make BOARD=pca10059 SERIAL=/dev/ttyACM0 all flash
|
||||
|
@ -50,7 +50,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = nRF52833_XXAA
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink
|
||||
flash: flash-jlink
|
||||
|
@ -40,7 +40,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32f405rg
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash target using on-board stlink
|
||||
flash: flash-stlink
|
||||
|
@ -48,7 +48,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = nRF52840_xxAA
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink
|
||||
flash: flash-jlink
|
||||
|
@ -1,7 +1,4 @@
|
||||
CFLAGS += \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-Wl,--gc-sections \
|
||||
-mthumb \
|
||||
-mabi=aapcs-linux \
|
||||
-mcpu=cortex-m0plus \
|
||||
@ -9,9 +6,7 @@ CFLAGS += \
|
||||
-D__SAMD11D14AM__ \
|
||||
-DCONF_DFLL_OVERWRITE_CALIBRATION=0 \
|
||||
-DOSC32K_OVERWRITE_CALIBRATION=0 \
|
||||
-DCFG_TUSB_MCU=OPT_MCU_SAMD11 \
|
||||
-fshort-enums \
|
||||
-Os
|
||||
-DCFG_TUSB_MCU=OPT_MCU_SAMD11
|
||||
|
||||
# All source paths should be relative to the top level.
|
||||
LD_FILE = hw/bsp/$(BOARD)/samd11d14am_flash.ld
|
||||
@ -45,9 +40,7 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = ATSAMD11D14
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using edbg
|
||||
flash: $(BUILD)/$(BOARD)-firmware.bin
|
||||
edbg -b -t samd11 -e -pv -f $<
|
||||
|
||||
|
@ -47,7 +47,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = ATSAMG55J19
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using edbg from https://github.com/ataradov/edbg
|
||||
flash: $(BUILD)/$(BOARD)-firmware.bin
|
||||
|
@ -39,7 +39,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = ATSAMD21G18
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink
|
||||
flash: flash-jlink
|
||||
|
@ -44,7 +44,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32f070rb
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash target using on-board stlink
|
||||
flash: flash-stlink
|
||||
|
@ -45,7 +45,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32f072rb
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash target using on-board stlink
|
||||
flash: flash-stlink
|
||||
|
@ -43,7 +43,6 @@ FREERTOS_PORT = ARM_CM3
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32f103c8
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash target ROM bootloader
|
||||
flash: $(BUILD)/$(BOARD)-firmware.bin
|
||||
|
@ -43,7 +43,6 @@ FREERTOS_PORT = ARM_CM3
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32f207zg
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash target using on-board stlink
|
||||
flash: flash-stlink
|
||||
|
@ -44,7 +44,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32f303vc
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash target using on-board stlink
|
||||
flash: flash-stlink
|
||||
|
@ -31,27 +31,29 @@
|
||||
// Forward USB interrupt events to TinyUSB IRQ Handler
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// USB defaults to using interrupts 19, 20, and 42 (based on SYSCFG_CFGR1.USB_IT_RMP)
|
||||
// USB defaults to using interrupts 19, 20 and 42, however, this BSP sets the
|
||||
// SYSCFG_CFGR1.USB_IT_RMP bit remapping interrupts to 74, 75 and 76.
|
||||
|
||||
// FIXME: Do all three need to be handled, or just the LP one?
|
||||
// USB high-priority interrupt (Channel 19): Triggered only by a correct
|
||||
// USB high-priority interrupt (Channel 74): Triggered only by a correct
|
||||
// transfer event for isochronous and double-buffer bulk transfer to reach
|
||||
// the highest possible transfer rate.
|
||||
void USB_HP_CAN_TX_IRQHandler(void)
|
||||
void USB_HP_IRQHandler(void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
// USB low-priority interrupt (Channel 20): Triggered by all USB events
|
||||
// USB low-priority interrupt (Channel 75): Triggered by all USB events
|
||||
// (Correct transfer, USB reset, etc.). The firmware has to check the
|
||||
// interrupt source before serving the interrupt.
|
||||
void USB_LP_CAN_RX0_IRQHandler(void)
|
||||
void USB_LP_IRQHandler(void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
// USB wakeup interrupt (Channel 42): Triggered by the wakeup event from the USB
|
||||
// USB wakeup interrupt (Channel 76): Triggered by the wakeup event from the USB
|
||||
// Suspend mode.
|
||||
void USBWakeUp_IRQHandler(void)
|
||||
void USBWakeUp_RMP_IRQHandler(void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
@ -127,6 +129,10 @@ void board_init(void)
|
||||
SysTick_Config(SystemCoreClock / 1000);
|
||||
#endif
|
||||
|
||||
// Remap the USB interrupts
|
||||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||
__HAL_REMAPINTERRUPT_USB_ENABLE();
|
||||
|
||||
// LED
|
||||
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
|
@ -40,7 +40,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32f401cc
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash target ROM bootloader
|
||||
flash: $(BUILD)/$(BOARD)-firmware.bin
|
||||
|
@ -44,7 +44,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32f407vg
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash target using on-board stlink
|
||||
flash: flash-stlink
|
||||
|
@ -40,7 +40,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32f411ce
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash target ROM bootloader
|
||||
flash: $(BUILD)/$(BOARD)-firmware.bin
|
||||
|
@ -44,7 +44,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32f411ve
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash target using on-board stlink
|
||||
flash: flash-stlink
|
||||
|
@ -45,7 +45,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32f41zx
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash target using on-board stlink
|
||||
flash: flash-stlink
|
||||
|
@ -57,7 +57,6 @@ FREERTOS_PORT = ARM_CM7/r0p1
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32h743xi
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash target using on-board stlink
|
||||
flash: flash-stlink
|
||||
|
@ -52,7 +52,6 @@ FREERTOS_PORT = ARM_CM7/r0p1
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32h745xi
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash target using on-board stlink
|
||||
flash: flash-stlink
|
||||
|
@ -44,7 +44,6 @@ FREERTOS_PORT = ARM_CM0
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = STM32L053R8
|
||||
JLINK_IF = swd
|
||||
|
||||
# Path to STM32 Cube Programmer CLI, should be added into system path
|
||||
STM32Prog = STM32_Programmer_CLI
|
||||
|
@ -43,7 +43,6 @@ FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32l476vg
|
||||
JLINK_IF = swd
|
||||
|
||||
# Path to STM32 Cube Programmer CLI, should be added into system path
|
||||
STM32Prog = STM32_Programmer_CLI
|
||||
|
@ -45,7 +45,6 @@ FREERTOS_PORT = ARM_CM7/r0p1
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = MIMXRT1062xxx6A
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash by using teensy_loader_cli https://github.com/PaulStoffregen/teensy_loader_cli
|
||||
# Make sure it is in your PATH
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 168322aa7100f60d6837505f5705fd61454dac27
|
||||
Subproject commit 434e384e8f1c6a05377f82e1f0796467a2267ad5
|
@ -2,6 +2,7 @@
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
* Copyright (c) 2020 Reinhard Panhuber
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -35,28 +36,44 @@
|
||||
#include "common/tusb_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// Audio Interface Subclass Codes
|
||||
/// Audio Device Class Codes
|
||||
|
||||
/// A.2 - Audio Function Subclass Codes
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_SUBCLASS_CONTROL = 0x01 , ///< Audio Control
|
||||
AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00,
|
||||
} audio_function_subclass_type_t;
|
||||
|
||||
/// A.3 - Audio Function Protocol Codes
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00,
|
||||
AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0
|
||||
} audio_function_protocol_code_t;
|
||||
|
||||
/// A.5 - Audio Interface Subclass Codes
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_SUBCLASS_UNDEFINED = 0x00,
|
||||
AUDIO_SUBCLASS_CONTROL , ///< Audio Control
|
||||
AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming
|
||||
AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming
|
||||
} audio_subclass_type_t;
|
||||
|
||||
/// Audio Protocol Codes
|
||||
/// A.6 - Audio Interface Protocol Codes
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_PROTOCOL_V1 = 0x00, ///< Version 1.0
|
||||
AUDIO_PROTOCOL_V2 = 0x20, ///< Version 2.0
|
||||
AUDIO_PROTOCOL_V3 = 0x30, ///< Version 3.0
|
||||
} audio_protocol_type_t;
|
||||
AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00,
|
||||
AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0
|
||||
} audio_interface_protocol_code_t;
|
||||
|
||||
/// Audio Function Category Codes
|
||||
/// A.7 - Audio Function Category Codes
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_FUNC_UNDEF = 0x00,
|
||||
AUDIO_FUNC_DESKTOP_SPEAKER = 0x01,
|
||||
AUDIO_FUNC_HOME_THEATER = 0x02,
|
||||
AUDIO_FUNC_MICROPHONE = 0x03,
|
||||
@ -68,33 +85,850 @@ typedef enum
|
||||
AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09,
|
||||
AUDIO_FUNC_PRO_AUDIO = 0x0A,
|
||||
AUDIO_FUNC_AUDIO_VIDEO = 0x0B,
|
||||
AUDIO_FUNC_CONTROL_PANEL = 0x0C
|
||||
} audio_function_t;
|
||||
AUDIO_FUNC_CONTROL_PANEL = 0x0C,
|
||||
AUDIO_FUNC_OTHER = 0xFF,
|
||||
} audio_function_code_t;
|
||||
|
||||
/// Audio Class-Specific AC Interface Descriptor Subtypes
|
||||
/// A.9 - Audio Class-Specific AC Interface Descriptor Subtypes UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CS_INTERFACE_HEADER = 0x01,
|
||||
AUDIO_CS_INTERFACE_INPUT_TERMINAL = 0x02,
|
||||
AUDIO_CS_INTERFACE_OUTPUT_TERMINAL = 0x03,
|
||||
AUDIO_CS_INTERFACE_MIXER_UNIT = 0x04,
|
||||
AUDIO_CS_INTERFACE_SELECTOR_UNIT = 0x05,
|
||||
AUDIO_CS_INTERFACE_FEATURE_UNIT = 0x06,
|
||||
AUDIO_CS_INTERFACE_EFFECT_UNIT = 0x07,
|
||||
AUDIO_CS_INTERFACE_PROCESSING_UNIT = 0x08,
|
||||
AUDIO_CS_INTERFACE_EXTENSION_UNIT = 0x09,
|
||||
AUDIO_CS_INTERFACE_CLOCK_SOURCE = 0x0A,
|
||||
AUDIO_CS_INTERFACE_CLOCK_SELECTOR = 0x0B,
|
||||
AUDIO_CS_INTERFACE_CLOCK_MULTIPLIER = 0x0C,
|
||||
AUDIO_CS_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D,
|
||||
} audio_cs_interface_subtype_t;
|
||||
AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00,
|
||||
AUDIO_CS_AC_INTERFACE_HEADER = 0x01,
|
||||
AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02,
|
||||
AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03,
|
||||
AUDIO_CS_AC_INTERFACE_MIXER_UNIT = 0x04,
|
||||
AUDIO_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05,
|
||||
AUDIO_CS_AC_INTERFACE_FEATURE_UNIT = 0x06,
|
||||
AUDIO_CS_AC_INTERFACE_EFFECT_UNIT = 0x07,
|
||||
AUDIO_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08,
|
||||
AUDIO_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09,
|
||||
AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A,
|
||||
AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B,
|
||||
AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C,
|
||||
AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D,
|
||||
} audio_cs_ac_interface_subtype_t;
|
||||
|
||||
/** @} */
|
||||
/// A.10 - Audio Class-Specific AS Interface Descriptor Subtypes UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00,
|
||||
AUDIO_CS_AS_INTERFACE_AS_GENERAL = 0x01,
|
||||
AUDIO_CS_AS_INTERFACE_FORMAT_TYPE = 0x02,
|
||||
AUDIO_CS_AS_INTERFACE_ENCODER = 0x03,
|
||||
AUDIO_CS_AS_INTERFACE_DECODER = 0x04,
|
||||
} audio_cs_as_interface_subtype_t;
|
||||
|
||||
/// A.11 - Effect Unit Effect Types
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_EFFECT_TYPE_UNDEF = 0x00,
|
||||
AUDIO_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01,
|
||||
AUDIO_EFFECT_TYPE_REVERBERATION = 0x02,
|
||||
AUDIO_EFFECT_TYPE_MOD_DELAY = 0x03,
|
||||
AUDIO_EFFECT_TYPE_DYN_RANGE_COMP = 0x04,
|
||||
} audio_effect_unit_effect_type_t;
|
||||
|
||||
/// A.12 - Processing Unit Process Types
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_PROCESS_TYPE_UNDEF = 0x00,
|
||||
AUDIO_PROCESS_TYPE_UP_DOWN_MIX = 0x01,
|
||||
AUDIO_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02,
|
||||
AUDIO_PROCESS_TYPE_STEREO_EXTENDER = 0x03,
|
||||
} audio_processing_unit_process_type_t;
|
||||
|
||||
/// A.13 - Audio Class-Specific EP Descriptor Subtypes UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CS_EP_SUBTYPE_UNDEF = 0x00,
|
||||
AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01,
|
||||
} audio_cs_ep_subtype_t;
|
||||
|
||||
/// A.14 - Audio Class-Specific Request Codes
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CS_REQ_UNDEF = 0x00,
|
||||
AUDIO_CS_REQ_CUR = 0x01,
|
||||
AUDIO_CS_REQ_RANGE = 0x02,
|
||||
AUDIO_CS_REQ_MEM = 0x03,
|
||||
} audio_cs_req_t;
|
||||
|
||||
/// A.17 - Control Selector Codes
|
||||
|
||||
/// A.17.1 - Clock Source Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CS_CTRL_UNDEF = 0x00,
|
||||
AUDIO_CS_CTRL_SAM_FREQ = 0x01,
|
||||
AUDIO_CS_CTRL_CLK_VALID = 0x02,
|
||||
} audio_clock_src_control_selector_t;
|
||||
|
||||
/// A.17.2 - Clock Selector Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CX_CTRL_UNDEF = 0x00,
|
||||
AUDIO_CX_CTRL_CONTROL = 0x01,
|
||||
} audio_clock_sel_control_selector_t;
|
||||
|
||||
/// A.17.3 - Clock Multiplier Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CM_CTRL_UNDEF = 0x00,
|
||||
AUDIO_CM_CTRL_NUMERATOR_CONTROL = 0x01,
|
||||
AUDIO_CM_CTRL_DENOMINATOR_CONTROL = 0x02,
|
||||
} audio_clock_mul_control_selector_t;
|
||||
|
||||
/// A.17.4 - Terminal Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_TE_CTRL_UNDEF = 0x00,
|
||||
AUDIO_TE_CTRL_COPY_PROTECT = 0x01,
|
||||
AUDIO_TE_CTRL_CONNECTOR = 0x02,
|
||||
AUDIO_TE_CTRL_OVERLOAD = 0x03,
|
||||
AUDIO_TE_CTRL_CLUSTER = 0x04,
|
||||
AUDIO_TE_CTRL_UNDERFLOW = 0x05,
|
||||
AUDIO_TE_CTRL_OVERFLOW = 0x06,
|
||||
AUDIO_TE_CTRL_LATENCY = 0x07,
|
||||
} audio_terminal_control_selector_t;
|
||||
|
||||
/// A.17.5 - Mixer Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_MU_CTRL_UNDEF = 0x00,
|
||||
AUDIO_MU_CTRL_MIXER = 0x01,
|
||||
AUDIO_MU_CTRL_CLUSTER = 0x02,
|
||||
AUDIO_MU_CTRL_UNDERFLOW = 0x03,
|
||||
AUDIO_MU_CTRL_OVERFLOW = 0x04,
|
||||
AUDIO_MU_CTRL_LATENCY = 0x05,
|
||||
} audio_mixer_control_selector_t;
|
||||
|
||||
/// A.17.6 - Selector Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_SU_CTRL_UNDEF = 0x00,
|
||||
AUDIO_SU_CTRL_SELECTOR = 0x01,
|
||||
AUDIO_SU_CTRL_LATENCY = 0x02,
|
||||
} audio_sel_control_selector_t;
|
||||
|
||||
/// A.17.7 - Feature Unit Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_FU_CTRL_UNDEF = 0x00,
|
||||
AUDIO_FU_CTRL_MUTE = 0x01,
|
||||
AUDIO_FU_CTRL_VOLUME = 0x02,
|
||||
AUDIO_FU_CTRL_BASS = 0x03,
|
||||
AUDIO_FU_CTRL_MID = 0x04,
|
||||
AUDIO_FU_CTRL_TREBLE = 0x05,
|
||||
AUDIO_FU_CTRL_GRAPHIC_EQUALIZER = 0x06,
|
||||
AUDIO_FU_CTRL_AGC = 0x07,
|
||||
AUDIO_FU_CTRL_DELAY = 0x08,
|
||||
AUDIO_FU_CTRL_BASS_BOOST = 0x09,
|
||||
AUDIO_FU_CTRL_LOUDNESS = 0x0A,
|
||||
AUDIO_FU_CTRL_INPUT_GAIN = 0x0B,
|
||||
AUDIO_FU_CTRL_GAIN_PAD = 0x0C,
|
||||
AUDIO_FU_CTRL_INVERTER = 0x0D,
|
||||
AUDIO_FU_CTRL_UNDERFLOW = 0x0E,
|
||||
AUDIO_FU_CTRL_OVERVLOW = 0x0F,
|
||||
AUDIO_FU_CTRL_LATENCY = 0x10,
|
||||
} audio_feature_unit_control_selector_t;
|
||||
|
||||
/// A.17.8 Effect Unit Control Selectors
|
||||
|
||||
/// A.17.8.1 Parametric Equalizer Section Effect Unit Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_PE_CTRL_UNDEF = 0x00,
|
||||
AUDIO_PE_CTRL_ENABLE = 0x01,
|
||||
AUDIO_PE_CTRL_CENTERFREQ = 0x02,
|
||||
AUDIO_PE_CTRL_QFACTOR = 0x03,
|
||||
AUDIO_PE_CTRL_GAIN = 0x04,
|
||||
AUDIO_PE_CTRL_UNDERFLOW = 0x05,
|
||||
AUDIO_PE_CTRL_OVERFLOW = 0x06,
|
||||
AUDIO_PE_CTRL_LATENCY = 0x07,
|
||||
} audio_parametric_equalizer_control_selector_t;
|
||||
|
||||
/// A.17.8.2 Reverberation Effect Unit Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_RV_CTRL_UNDEF = 0x00,
|
||||
AUDIO_RV_CTRL_ENABLE = 0x01,
|
||||
AUDIO_RV_CTRL_TYPE = 0x02,
|
||||
AUDIO_RV_CTRL_LEVEL = 0x03,
|
||||
AUDIO_RV_CTRL_TIME = 0x04,
|
||||
AUDIO_RV_CTRL_FEEDBACK = 0x05,
|
||||
AUDIO_RV_CTRL_PREDELAY = 0x06,
|
||||
AUDIO_RV_CTRL_DENSITY = 0x07,
|
||||
AUDIO_RV_CTRL_HIFREQ_ROLLOFF = 0x08,
|
||||
AUDIO_RV_CTRL_UNDERFLOW = 0x09,
|
||||
AUDIO_RV_CTRL_OVERFLOW = 0x0A,
|
||||
AUDIO_RV_CTRL_LATENCY = 0x0B,
|
||||
} audio_reverberation_effect_control_selector_t;
|
||||
|
||||
/// A.17.8.3 Modulation Delay Effect Unit Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_MD_CTRL_UNDEF = 0x00,
|
||||
AUDIO_MD_CTRL_ENABLE = 0x01,
|
||||
AUDIO_MD_CTRL_BALANCE = 0x02,
|
||||
AUDIO_MD_CTRL_RATE = 0x03,
|
||||
AUDIO_MD_CTRL_DEPTH = 0x04,
|
||||
AUDIO_MD_CTRL_TIME = 0x05,
|
||||
AUDIO_MD_CTRL_FEEDBACK = 0x06,
|
||||
AUDIO_MD_CTRL_UNDERFLOW = 0x07,
|
||||
AUDIO_MD_CTRL_OVERFLOW = 0x08,
|
||||
AUDIO_MD_CTRL_LATENCY = 0x09,
|
||||
} audio_modulation_delay_control_selector_t;
|
||||
|
||||
/// A.17.8.4 Dynamic Range Compressor Effect Unit Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_DR_CTRL_UNDEF = 0x00,
|
||||
AUDIO_DR_CTRL_ENABLE = 0x01,
|
||||
AUDIO_DR_CTRL_COMPRESSION_RATE = 0x02,
|
||||
AUDIO_DR_CTRL_MAXAMPL = 0x03,
|
||||
AUDIO_DR_CTRL_THRESHOLD = 0x04,
|
||||
AUDIO_DR_CTRL_ATTACK_TIME = 0x05,
|
||||
AUDIO_DR_CTRL_RELEASE_TIME = 0x06,
|
||||
AUDIO_DR_CTRL_UNDERFLOW = 0x07,
|
||||
AUDIO_DR_CTRL_OVERFLOW = 0x08,
|
||||
AUDIO_DR_CTRL_LATENCY = 0x09,
|
||||
} audio_dynamic_range_compression_control_selector_t;
|
||||
|
||||
/// A.17.9 Processing Unit Control Selectors
|
||||
|
||||
/// A.17.9.1 Up/Down-mix Processing Unit Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_UD_CTRL_UNDEF = 0x00,
|
||||
AUDIO_UD_CTRL_ENABLE = 0x01,
|
||||
AUDIO_UD_CTRL_MODE_SELECT = 0x02,
|
||||
AUDIO_UD_CTRL_CLUSTER = 0x03,
|
||||
AUDIO_UD_CTRL_UNDERFLOW = 0x04,
|
||||
AUDIO_UD_CTRL_OVERFLOW = 0x05,
|
||||
AUDIO_UD_CTRL_LATENCY = 0x06,
|
||||
} audio_up_down_mix_control_selector_t;
|
||||
|
||||
/// A.17.9.2 Dolby Prologic ™ Processing Unit Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_DP_CTRL_UNDEF = 0x00,
|
||||
AUDIO_DP_CTRL_ENABLE = 0x01,
|
||||
AUDIO_DP_CTRL_MODE_SELECT = 0x02,
|
||||
AUDIO_DP_CTRL_CLUSTER = 0x03,
|
||||
AUDIO_DP_CTRL_UNDERFLOW = 0x04,
|
||||
AUDIO_DP_CTRL_OVERFLOW = 0x05,
|
||||
AUDIO_DP_CTRL_LATENCY = 0x06,
|
||||
} audio_dolby_prologic_control_selector_t;
|
||||
|
||||
/// A.17.9.3 Stereo Extender Processing Unit Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_ST_EXT_CTRL_UNDEF = 0x00,
|
||||
AUDIO_ST_EXT_CTRL_ENABLE = 0x01,
|
||||
AUDIO_ST_EXT_CTRL_WIDTH = 0x02,
|
||||
AUDIO_ST_EXT_CTRL_UNDERFLOW = 0x03,
|
||||
AUDIO_ST_EXT_CTRL_OVERFLOW = 0x04,
|
||||
AUDIO_ST_EXT_CTRL_LATENCY = 0x05,
|
||||
} audio_stereo_extender_control_selector_t;
|
||||
|
||||
/// A.17.10 Extension Unit Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_XU_CTRL_UNDEF = 0x00,
|
||||
AUDIO_XU_CTRL_ENABLE = 0x01,
|
||||
AUDIO_XU_CTRL_CLUSTER = 0x02,
|
||||
AUDIO_XU_CTRL_UNDERFLOW = 0x03,
|
||||
AUDIO_XU_CTRL_OVERFLOW = 0x04,
|
||||
AUDIO_XU_CTRL_LATENCY = 0x05,
|
||||
} audio_extension_unit_control_selector_t;
|
||||
|
||||
/// A.17.11 AudioStreaming Interface Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_AS_CTRL_UNDEF = 0x00,
|
||||
AUDIO_AS_CTRL_ACT_ALT_SETTING = 0x01,
|
||||
AUDIO_AS_CTRL_VAL_ALT_SETTINGS = 0x02,
|
||||
AUDIO_AS_CTRL_AUDIO_DATA_FORMAT = 0x03,
|
||||
} audio_audiostreaming_interface_control_selector_t;
|
||||
|
||||
/// A.17.12 Encoder Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_EN_CTRL_UNDEF = 0x00,
|
||||
AUDIO_EN_CTRL_BIT_RATE = 0x01,
|
||||
AUDIO_EN_CTRL_QUALITY = 0x02,
|
||||
AUDIO_EN_CTRL_VBR = 0x03,
|
||||
AUDIO_EN_CTRL_TYPE = 0x04,
|
||||
AUDIO_EN_CTRL_UNDERFLOW = 0x05,
|
||||
AUDIO_EN_CTRL_OVERFLOW = 0x06,
|
||||
AUDIO_EN_CTRL_ENCODER_ERROR = 0x07,
|
||||
AUDIO_EN_CTRL_PARAM1 = 0x08,
|
||||
AUDIO_EN_CTRL_PARAM2 = 0x09,
|
||||
AUDIO_EN_CTRL_PARAM3 = 0x0A,
|
||||
AUDIO_EN_CTRL_PARAM4 = 0x0B,
|
||||
AUDIO_EN_CTRL_PARAM5 = 0x0C,
|
||||
AUDIO_EN_CTRL_PARAM6 = 0x0D,
|
||||
AUDIO_EN_CTRL_PARAM7 = 0x0E,
|
||||
AUDIO_EN_CTRL_PARAM8 = 0x0F,
|
||||
} audio_encoder_control_selector_t;
|
||||
|
||||
/// A.17.13 Decoder Control Selectors
|
||||
|
||||
/// A.17.13.1 MPEG Decoder Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_MPD_CTRL_UNDEF = 0x00,
|
||||
AUDIO_MPD_CTRL_DUAL_CHANNEL = 0x01,
|
||||
AUDIO_MPD_CTRL_SECOND_STEREO = 0x02,
|
||||
AUDIO_MPD_CTRL_MULTILINGUAL = 0x03,
|
||||
AUDIO_MPD_CTRL_DYN_RANGE = 0x04,
|
||||
AUDIO_MPD_CTRL_SCALING = 0x05,
|
||||
AUDIO_MPD_CTRL_HILO_SCALING = 0x06,
|
||||
AUDIO_MPD_CTRL_UNDERFLOW = 0x07,
|
||||
AUDIO_MPD_CTRL_OVERFLOW = 0x08,
|
||||
AUDIO_MPD_CTRL_DECODER_ERROR = 0x09,
|
||||
} audio_MPEG_decoder_control_selector_t;
|
||||
|
||||
/// A.17.13.2 AC-3 Decoder Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_AD_CTRL_UNDEF = 0x00,
|
||||
AUDIO_AD_CTRL_MODE = 0x01,
|
||||
AUDIO_AD_CTRL_DYN_RANGE = 0x02,
|
||||
AUDIO_AD_CTRL_SCALING = 0x03,
|
||||
AUDIO_AD_CTRL_HILO_SCALING = 0x04,
|
||||
AUDIO_AD_CTRL_UNDERFLOW = 0x05,
|
||||
AUDIO_AD_CTRL_OVERFLOW = 0x06,
|
||||
AUDIO_AD_CTRL_DECODER_ERROR = 0x07,
|
||||
} audio_AC3_decoder_control_selector_t;
|
||||
|
||||
/// A.17.13.3 WMA Decoder Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_WD_CTRL_UNDEF = 0x00,
|
||||
AUDIO_WD_CTRL_UNDERFLOW = 0x01,
|
||||
AUDIO_WD_CTRL_OVERFLOW = 0x02,
|
||||
AUDIO_WD_CTRL_DECODER_ERROR = 0x03,
|
||||
} audio_WMA_decoder_control_selector_t;
|
||||
|
||||
/// A.17.13.4 DTS Decoder Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_DD_CTRL_UNDEF = 0x00,
|
||||
AUDIO_DD_CTRL_UNDERFLOW = 0x01,
|
||||
AUDIO_DD_CTRL_OVERFLOW = 0x02,
|
||||
AUDIO_DD_CTRL_DECODER_ERROR = 0x03,
|
||||
} audio_DTS_decoder_control_selector_t;
|
||||
|
||||
/// A.17.14 Endpoint Control Selectors
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_EP_CTRL_UNDEF = 0x00,
|
||||
AUDIO_EP_CTRL_PITCH = 0x01,
|
||||
AUDIO_EP_CTRL_DATA_OVERRUN = 0x02,
|
||||
AUDIO_EP_CTRL_DATA_UNDERRUN = 0x03,
|
||||
} audio_EP_control_selector_t;
|
||||
|
||||
/// Terminal Types
|
||||
|
||||
/// 2.1 - Audio Class-Terminal Types UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100,
|
||||
AUDIO_TERM_TYPE_USB_STREAMING = 0x0101,
|
||||
AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF,
|
||||
} audio_terminal_type_t;
|
||||
|
||||
/// 2.2 - Audio Class-Input Terminal Types UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200,
|
||||
AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201,
|
||||
AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202,
|
||||
AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203,
|
||||
AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204,
|
||||
AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205,
|
||||
AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206,
|
||||
} audio_terminal_input_type_t;
|
||||
|
||||
/// 2.3 - Audio Class-Output Terminal Types UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300,
|
||||
AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301,
|
||||
AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302,
|
||||
AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303,
|
||||
AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304,
|
||||
AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305,
|
||||
AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306,
|
||||
AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307,
|
||||
} audio_terminal_output_type_t;
|
||||
|
||||
/// Rest is yet to be implemented
|
||||
|
||||
/// Additional Audio Device Class Codes - Source: Audio Data Formats
|
||||
|
||||
/// A.1 - Audio Class-Format Type Codes UAC2
|
||||
//typedef enum
|
||||
//{
|
||||
// AUDIO_FORMAT_TYPE_UNDEFINED = 0x00,
|
||||
// AUDIO_FORMAT_TYPE_I = 0x01,
|
||||
// AUDIO_FORMAT_TYPE_II = 0x02,
|
||||
// AUDIO_FORMAT_TYPE_III = 0x03,
|
||||
// AUDIO_FORMAT_TYPE_IV = 0x04,
|
||||
// AUDIO_EXT_FORMAT_TYPE_I = 0x81,
|
||||
// AUDIO_EXT_FORMAT_TYPE_II = 0x82,
|
||||
// AUDIO_EXT_FORMAT_TYPE_III = 0x83,
|
||||
//} audio_format_type_t;
|
||||
|
||||
#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00
|
||||
#define AUDIO_FORMAT_TYPE_I 0x01
|
||||
#define AUDIO_FORMAT_TYPE_II 0x02
|
||||
#define AUDIO_FORMAT_TYPE_III 0x03
|
||||
#define AUDIO_FORMAT_TYPE_IV 0x04
|
||||
#define AUDIO_EXT_FORMAT_TYPE_I 0x81
|
||||
#define AUDIO_EXT_FORMAT_TYPE_II 0x82
|
||||
#define AUDIO_EXT_FORMAT_TYPE_III 0x83
|
||||
|
||||
/// A.2.1 - Audio Class-Audio Data Format Type I UAC2
|
||||
//typedef enum
|
||||
//{
|
||||
// AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0),
|
||||
// AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1),
|
||||
// AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2),
|
||||
// AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3),
|
||||
// AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4),
|
||||
// AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000,
|
||||
//} audio_data_format_type_I_t;
|
||||
|
||||
#define AUDIO_DATA_FORMAT_TYPE_I_PCM ((uint32_t) (1 << 0))
|
||||
#define AUDIO_DATA_FORMAT_TYPE_I_PCM8 ((uint32_t) (1 << 1))
|
||||
#define AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT ((uint32_t) (1 << 2))
|
||||
#define AUDIO_DATA_FORMAT_TYPE_I_ALAW ((uint32_t) (1 << 3))
|
||||
#define AUDIO_DATA_FORMAT_TYPE_I_MULAW ((uint32_t) (1 << 4))
|
||||
#define AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA 0x100000000
|
||||
|
||||
/// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification
|
||||
|
||||
/// Isochronous End Point Attributes
|
||||
typedef enum
|
||||
{
|
||||
TUSB_ISO_EP_ATT_NO_SYNC = 0x00,
|
||||
TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04,
|
||||
TUSB_ISO_EP_ATT_ADAPTIVE = 0x08,
|
||||
TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C,
|
||||
TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point
|
||||
TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point
|
||||
TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback
|
||||
} tusb_iso_ep_attribute_t;
|
||||
|
||||
/// Audio Class-Control Values UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CTRL_NONE = 0x00, ///< No Host access
|
||||
AUDIO_CTRL_R = 0x01, ///< Host read access only
|
||||
AUDIO_CTRL_RW = 0x03, ///< Host read write access
|
||||
} audio_control_t;
|
||||
|
||||
/// Audio Class-Specific AC Interface Descriptor Controls UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0,
|
||||
} audio_cs_ac_interface_control_pos_t;
|
||||
|
||||
/// Audio Class-Specific AS Interface Descriptor Controls UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0,
|
||||
AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2,
|
||||
} audio_cs_as_interface_control_pos_t;
|
||||
|
||||
/// Audio Class-Specific AS Isochronous Data EP Attributes UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80,
|
||||
AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00,
|
||||
} audio_cs_as_iso_data_ep_attribute_t;
|
||||
|
||||
/// Audio Class-Specific AS Isochronous Data EP Controls UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0,
|
||||
AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2,
|
||||
AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4,
|
||||
} audio_cs_as_iso_data_ep_control_pos_t;
|
||||
|
||||
/// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00,
|
||||
AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01,
|
||||
AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02,
|
||||
} audio_cs_as_iso_data_ep_lock_delay_unit_t;
|
||||
|
||||
/// Audio Class-Clock Source Attributes UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CLOCK_SOURCE_ATT_EXT_CLK = 0x00,
|
||||
AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01,
|
||||
AUDIO_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02,
|
||||
AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03,
|
||||
AUDIO_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04,
|
||||
} audio_clock_source_attribute_t;
|
||||
|
||||
/// Audio Class-Clock Source Controls UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0,
|
||||
AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2,
|
||||
} audio_clock_source_control_pos_t;
|
||||
|
||||
/// Audio Class-Clock Selector Controls UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CLOCK_SELECTOR_CTRL_POS = 0,
|
||||
} audio_clock_selector_control_pos_t;
|
||||
|
||||
/// Audio Class-Clock Multiplier Controls UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0,
|
||||
AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2,
|
||||
} audio_clock_multiplier_control_pos_t;
|
||||
|
||||
/// Audio Class-Input Terminal Controls UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_IN_TERM_CTRL_CPY_PROT_POS = 0,
|
||||
AUDIO_IN_TERM_CTRL_CONNECTOR_POS = 2,
|
||||
AUDIO_IN_TERM_CTRL_OVERLOAD_POS = 4,
|
||||
AUDIO_IN_TERM_CTRL_CLUSTER_POS = 6,
|
||||
AUDIO_IN_TERM_CTRL_UNDERFLOW_POS = 8,
|
||||
AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10,
|
||||
} audio_terminal_input_control_pos_t;
|
||||
|
||||
/// Audio Class-Output Terminal Controls UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_OUT_TERM_CTRL_CPY_PROT_POS = 0,
|
||||
AUDIO_OUT_TERM_CTRL_CONNECTOR_POS = 2,
|
||||
AUDIO_OUT_TERM_CTRL_OVERLOAD_POS = 4,
|
||||
AUDIO_OUT_TERM_CTRL_UNDERFLOW_POS = 6,
|
||||
AUDIO_OUT_TERM_CTRL_OVERFLOW_POS = 8,
|
||||
} audio_terminal_output_control_pos_t;
|
||||
|
||||
/// Audio Class-Feature Unit Controls UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_FEATURE_UNIT_CTRL_MUTE_POS = 0,
|
||||
AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS = 2,
|
||||
AUDIO_FEATURE_UNIT_CTRL_BASS_POS = 4,
|
||||
AUDIO_FEATURE_UNIT_CTRL_MID_POS = 6,
|
||||
AUDIO_FEATURE_UNIT_CTRL_TREBLE_POS = 8,
|
||||
AUDIO_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10,
|
||||
AUDIO_FEATURE_UNIT_CTRL_AGC_POS = 12,
|
||||
AUDIO_FEATURE_UNIT_CTRL_DELAY_POS = 14,
|
||||
AUDIO_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16,
|
||||
AUDIO_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18,
|
||||
AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20,
|
||||
AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22,
|
||||
AUDIO_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24,
|
||||
AUDIO_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26,
|
||||
AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28,
|
||||
} audio_feature_unit_control_pos_t;
|
||||
|
||||
/// Audio Class-Audio Channel Configuration UAC2
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000,
|
||||
AUDIO_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001,
|
||||
AUDIO_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002,
|
||||
AUDIO_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004,
|
||||
AUDIO_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008,
|
||||
AUDIO_CHANNEL_CONFIG_BACK_LEFT = 0x00000010,
|
||||
AUDIO_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020,
|
||||
AUDIO_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040,
|
||||
AUDIO_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080,
|
||||
AUDIO_CHANNEL_CONFIG_BACK_CENTER = 0x00000100,
|
||||
AUDIO_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200,
|
||||
AUDIO_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400,
|
||||
AUDIO_CHANNEL_CONFIG_TOP_CENTER = 0x00000800,
|
||||
AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000,
|
||||
AUDIO_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000,
|
||||
AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000,
|
||||
AUDIO_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000,
|
||||
AUDIO_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000,
|
||||
AUDIO_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000,
|
||||
AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000,
|
||||
AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000,
|
||||
AUDIO_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000,
|
||||
AUDIO_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000,
|
||||
AUDIO_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000,
|
||||
AUDIO_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000,
|
||||
AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000,
|
||||
AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000,
|
||||
AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000,
|
||||
AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000,
|
||||
} audio_channel_config_t;
|
||||
|
||||
/// AUDIO Channel Cluster Descriptor (4.1)
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bNrChannels; ///< Number of channels currently connected.
|
||||
audio_channel_config_t bmChannelConfig; ///< Bitmap according to 'audio_channel_config_t' with a 1 set if channel is connected and 0 else. In case channels are non-predefined ignore them here (see UAC2 specification 4.1 Audio Channel Cluster Descriptor.
|
||||
uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first inserted channel with a non-predefined spatial location.
|
||||
} audio_desc_channel_cluster_t;
|
||||
|
||||
/// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2)
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
uint8_t bLength ; ///< Size of this descriptor in bytes: 9.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE.
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER.
|
||||
uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200).
|
||||
uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t.
|
||||
uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors.
|
||||
uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t.
|
||||
} audio_desc_cs_ac_interface_t;
|
||||
|
||||
/// AUDIO Clock Source Descriptor (4.7.2.1)
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
uint8_t bLength ; ///< Size of this descriptor in bytes: 8.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE.
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE.
|
||||
uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity.
|
||||
uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t.
|
||||
uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t.
|
||||
uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source.
|
||||
uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity.
|
||||
} audio_desc_clock_source_t;
|
||||
|
||||
/// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE.
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR.
|
||||
uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity.
|
||||
uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1.
|
||||
uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected..
|
||||
uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t.
|
||||
uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity.
|
||||
} audio_desc_clock_selector_t;
|
||||
|
||||
/// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins
|
||||
#define audio_desc_clock_selector_n_t(source_num) \
|
||||
struct TU_ATTR_PACKED { \
|
||||
uint8_t bLength ; \
|
||||
uint8_t bDescriptorType ; \
|
||||
uint8_t bDescriptorSubType ; \
|
||||
uint8_t bClockID ; \
|
||||
uint8_t bNrInPins ; \
|
||||
struct TU_ATTR_PACKED { \
|
||||
uint8_t baSourceID ; \
|
||||
} sourceID[source_num] ; \
|
||||
uint8_t bmControls ; \
|
||||
uint8_t iClockSource ; \
|
||||
}
|
||||
|
||||
/// AUDIO Clock Multiplier Descriptor (4.7.2.3)
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
uint8_t bLength ; ///< Size of this descriptor, in bytes: 7.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE.
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER.
|
||||
uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity.
|
||||
uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected.
|
||||
uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t.
|
||||
uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity.
|
||||
} audio_desc_clock_multiplier_t;
|
||||
|
||||
/// AUDIO Input Terminal Descriptor(4.7.2.4)
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
uint8_t bLength ; ///< Size of this descriptor, in bytes: 17.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE.
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL.
|
||||
uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types.
|
||||
uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated.
|
||||
uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected.
|
||||
uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster.
|
||||
uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t.
|
||||
uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t.
|
||||
uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal.
|
||||
} audio_desc_input_terminal_t;
|
||||
|
||||
/// AUDIO Output Terminal Descriptor(4.7.2.5)
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
uint8_t bLength ; ///< Size of this descriptor, in bytes: 12.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE.
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL.
|
||||
uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal.
|
||||
uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types.
|
||||
uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated.
|
||||
uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected.
|
||||
uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected.
|
||||
uint16_t bmControls ; ///< See: audio_terminal_output_type_t.
|
||||
uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal.
|
||||
} audio_desc_output_terminal_t;
|
||||
|
||||
/// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
uint8_t bLength ; ///< Size of this descriptor, in bytes: 14.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE.
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT.
|
||||
uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit.
|
||||
uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected.
|
||||
struct TU_ATTR_PACKED {
|
||||
uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1.
|
||||
} controls[2] ;
|
||||
uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit.
|
||||
} audio_desc_feature_unit_t;
|
||||
|
||||
/// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels
|
||||
#define audio_desc_feature_unit_n_t(ch_num)\
|
||||
struct TU_ATTR_PACKED { \
|
||||
uint8_t bLength ; /* 6+(ch_num+1)*4 */\
|
||||
uint8_t bDescriptorType ; \
|
||||
uint8_t bDescriptorSubType ; \
|
||||
uint8_t bUnitID ; \
|
||||
uint8_t bSourceID ; \
|
||||
struct TU_ATTR_PACKED { \
|
||||
uint32_t bmaControls ; \
|
||||
} controls[ch_num+1] ; \
|
||||
uint8_t iTerminal ; \
|
||||
}
|
||||
|
||||
/// AUDIO Class-Specific AS Interface Descriptor(4.9.2)
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
uint8_t bLength ; ///< Size of this descriptor, in bytes: 16.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE.
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL.
|
||||
uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected.
|
||||
uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t.
|
||||
uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t.
|
||||
uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t.
|
||||
uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster.
|
||||
uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t.
|
||||
uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel.
|
||||
} audio_desc_cs_as_interface_t;
|
||||
|
||||
/// AUDIO Type I Format Type Descriptor(2.3.1.6 - Audio Formats)
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
uint8_t bLength ; ///< Size of this descriptor, in bytes: 6.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE.
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE.
|
||||
uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I.
|
||||
uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4.
|
||||
uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot.
|
||||
} audio_desc_type_I_format_t;
|
||||
|
||||
/// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2)
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
uint8_t bLength ; ///< Size of this descriptor, in bytes: 8.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT.
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL.
|
||||
uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t.
|
||||
uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t.
|
||||
uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t.
|
||||
uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field.
|
||||
} audio_desc_cs_as_iso_data_ep_t;
|
||||
|
||||
//// 5.2.3 Control Request Parameter Block Layout
|
||||
|
||||
// 5.2.3.1 1-byte Control CUR Parameter Block
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control
|
||||
} audio_control_cur_1_t;
|
||||
|
||||
// 5.2.3.2 2-byte Control CUR Parameter Block
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control
|
||||
} audio_control_cur_2_t;
|
||||
|
||||
// 5.2.3.3 4-byte Control CUR Parameter Block
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control
|
||||
} audio_control_cur_4_t;
|
||||
|
||||
// Use the following ONLY for RECEIVED data - compiler does not know how many subranges are defined! Use the one below for predefined lengths - or if you know what you are doing do what you like
|
||||
// 5.2.3.1 1-byte Control RANGE Parameter Block
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint16_t wNumSubRanges;
|
||||
struct TU_ATTR_PACKED {
|
||||
int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/
|
||||
int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/
|
||||
uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/
|
||||
} subrange[] ;
|
||||
} audio_control_range_1_t;
|
||||
|
||||
// 5.2.3.2 2-byte Control RANGE Parameter Block
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint16_t wNumSubRanges;
|
||||
struct TU_ATTR_PACKED {
|
||||
int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/
|
||||
int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/
|
||||
uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/
|
||||
} subrange[] ;
|
||||
} audio_control_range_2_t;
|
||||
|
||||
// 5.2.3.3 4-byte Control RANGE Parameter Block
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint16_t wNumSubRanges;
|
||||
struct TU_ATTR_PACKED {
|
||||
int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/
|
||||
int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/
|
||||
uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/
|
||||
} subrange[] ;
|
||||
} audio_control_range_4_t;
|
||||
|
||||
// 5.2.3.1 1-byte Control RANGE Parameter Block
|
||||
#define audio_control_range_1_n_t(numSubRanges) \
|
||||
struct TU_ATTR_PACKED { \
|
||||
uint16_t wNumSubRanges; \
|
||||
struct TU_ATTR_PACKED { \
|
||||
int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\
|
||||
int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\
|
||||
uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\
|
||||
} subrange[numSubRanges] ; \
|
||||
}
|
||||
|
||||
/// 5.2.3.2 2-byte Control RANGE Parameter Block
|
||||
#define audio_control_range_2_n_t(numSubRanges) \
|
||||
struct TU_ATTR_PACKED { \
|
||||
uint16_t wNumSubRanges; \
|
||||
struct TU_ATTR_PACKED { \
|
||||
int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\
|
||||
int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\
|
||||
uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\
|
||||
} subrange[numSubRanges]; \
|
||||
}
|
||||
|
||||
// 5.2.3.3 4-byte Control RANGE Parameter Block
|
||||
#define audio_control_range_4_n_t(numSubRanges) \
|
||||
struct TU_ATTR_PACKED { \
|
||||
uint16_t wNumSubRanges; \
|
||||
struct TU_ATTR_PACKED { \
|
||||
int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\
|
||||
int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\
|
||||
uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\
|
||||
} subrange[numSubRanges]; \
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
1448
src/class/audio/audio_device.c
Normal file
1448
src/class/audio/audio_device.c
Normal file
File diff suppressed because it is too large
Load Diff
401
src/class/audio/audio_device.h
Normal file
401
src/class/audio/audio_device.h
Normal file
@ -0,0 +1,401 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 Ha Thach (tinyusb.org)
|
||||
* Copyright (c) 2020 Reinhard Panhuber
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#ifndef _TUSB_AUDIO_DEVICE_H_
|
||||
#define _TUSB_AUDIO_DEVICE_H_
|
||||
|
||||
#include "assert.h"
|
||||
#include "common/tusb_common.h"
|
||||
#include "device/usbd.h"
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Class Driver Configuration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// 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 waste a few bytes)
|
||||
#ifndef CFG_TUD_AUDIO_N_AS_INT
|
||||
#define CFG_TUD_AUDIO_N_AS_INT 0
|
||||
#endif
|
||||
|
||||
// Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors
|
||||
#ifndef CFG_TUD_AUDIO_CTRL_BUF_SIZE
|
||||
#error You must define an audio class control request buffer size!
|
||||
#endif
|
||||
|
||||
// Use of TX/RX FIFOs - If sizes are not zero, audio.c implements FIFOs for RX and TX (whatever defined).
|
||||
// For RX: the input stream gets decoded into its corresponding channels, where for each channel a FIFO is setup to hold its data -> see: audio_rx_done_cb().
|
||||
// For TX: the output stream is composed from CFG_TUD_AUDIO_N_CHANNELS_TX channels, where for each channel a FIFO is defined.
|
||||
// Further, it implements encoding and decoding of the individual channels (parameterized by the defines below).
|
||||
// If you don't use the FIFOs you need to handle encoding and decoding on your own in audio_rx_done_cb() and audio_tx_done_cb(). This, however, allows for optimizations.
|
||||
|
||||
#ifndef CFG_TUD_AUDIO_TX_FIFO_SIZE
|
||||
#define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_AUDIO_RX_FIFO_SIZE
|
||||
#define CFG_TUD_AUDIO_RX_FIFO_SIZE 0 // Buffer size per channel
|
||||
#endif
|
||||
|
||||
// End point sizes - Limits: Full Speed <= 1023, High Speed <= 1024
|
||||
#ifndef CFG_TUD_AUDIO_EPSIZE_IN
|
||||
#define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_AUDIO_EPSIZE_OUT
|
||||
#define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
|
||||
#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
|
||||
#ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE
|
||||
#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_AUDIO_N_CHANNELS_TX
|
||||
#define CFG_TUD_AUDIO_N_CHANNELS_TX 1
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_AUDIO_N_CHANNELS_RX
|
||||
#define CFG_TUD_AUDIO_N_CHANNELS_RX 1
|
||||
#endif
|
||||
|
||||
// Audio data format types
|
||||
#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_TX
|
||||
#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, an encoding function has to be implemented in audio_device.c
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_RX
|
||||
#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, a decoding function has to be implemented in audio_device.c
|
||||
#endif
|
||||
|
||||
// Audio data format type I specifications
|
||||
#if CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I
|
||||
|
||||
// Type definitions - for possible formats see: audio_data_format_type_I_t and further in UAC2 specifications.
|
||||
#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_TX
|
||||
#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize
|
||||
#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_AUDIO_TX_ITEMSIZE
|
||||
#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1
|
||||
#define CFG_TUD_AUDIO_TX_ITEMSIZE 1
|
||||
#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2
|
||||
#define CFG_TUD_AUDIO_TX_ITEMSIZE 2
|
||||
#else
|
||||
#define CFG_TUD_AUDIO_TX_ITEMSIZE 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_TX_ITEMSIZE < CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX
|
||||
#error FIFO element size (ITEMSIZE) must not be smaller then sample size
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I
|
||||
|
||||
#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_RX
|
||||
#define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize
|
||||
#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1
|
||||
#define CFG_TUD_AUDIO_RX_ITEMSIZE 1
|
||||
#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 2
|
||||
#define CFG_TUD_AUDIO_RX_ITEMSIZE 2
|
||||
#else
|
||||
#define CFG_TUD_AUDIO_RX_ITEMSIZE 4
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!");
|
||||
|
||||
// Supported types of this driver:
|
||||
// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \addtogroup AUDIO_Serial Serial
|
||||
* @{
|
||||
* \defgroup AUDIO_Serial_Device Device
|
||||
* @{ */
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Application API (Multiple Interfaces)
|
||||
// CFG_TUD_AUDIO > 1
|
||||
//--------------------------------------------------------------------+
|
||||
bool tud_audio_n_mounted (uint8_t itf);
|
||||
|
||||
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
|
||||
#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1
|
||||
uint16_t tud_audio_n_available (uint8_t itf, uint8_t channelId);
|
||||
uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize);
|
||||
void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId);
|
||||
#else
|
||||
uint16_t tud_audio_n_available (uint8_t itf);
|
||||
uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize);
|
||||
void tud_audio_n_read_flush (uint8_t itf);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers
|
||||
#if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE
|
||||
uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len)
|
||||
#endif
|
||||
*/
|
||||
|
||||
#ifndef CFG_TUD_AUDIO_TX_FIFO_COUNT
|
||||
#define CFG_TUD_AUDIO_TX_FIFO_COUNT 1
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
|
||||
#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1
|
||||
uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, const void * data, uint16_t len);
|
||||
#else
|
||||
uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len);
|
||||
#endif
|
||||
uint16_t tud_audio_n_write_flush(uint8_t itf);
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0
|
||||
uint16_t tud_audio_int_ctr_n_available (uint8_t itf);
|
||||
uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize);
|
||||
void tud_audio_int_ctr_n_read_flush (uint8_t itf);
|
||||
uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t bufsize);
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Application API (Interface0)
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
static inline bool tud_audio_mounted (void);
|
||||
|
||||
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
|
||||
static inline uint16_t tud_audio_available (void);
|
||||
static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize);
|
||||
static inline void tud_audio_read_flush (void);
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
|
||||
#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1
|
||||
static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize);
|
||||
#else
|
||||
static inline uint16_t tud_audio_write (uint8_t const* buffer, uint16_t bufsize);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0
|
||||
static inline uint32_t tud_audio_int_ctr_available (void);
|
||||
static inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize);
|
||||
static inline void tud_audio_int_ctr_read_flush (void);
|
||||
static inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize);
|
||||
#endif
|
||||
|
||||
// Buffer control EP data and schedule a transmit
|
||||
// This function is intended to be used if you do not have a persistent buffer or memory location available (e.g. non-local variables) and need to answer onto a
|
||||
// get request. This function buffers your answer request frame into the control buffer of the corresponding audio driver and schedules a transmit for sending it.
|
||||
// Since transmission is triggered via interrupts, a persistent memory location is required onto which the buffer pointer in pointing. If you already have such
|
||||
// available you may directly use 'tud_control_xfer(...)'. In this case data does not need to be copied into an additional buffer and you save some time.
|
||||
// If the request's wLength is zero, a status packet is sent instead.
|
||||
bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Application Callback API (weak is optional)
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#if CFG_TUD_AUDIO_EPSIZE_IN
|
||||
TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting);
|
||||
TU_ATTR_WEAK 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);
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_EPSIZE_OUT
|
||||
TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize);
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||
TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport);
|
||||
// User code should call this function with feedback value in 16.16 format for FS and HS.
|
||||
// Value will be corrected for FS to 10.14 format automatically.
|
||||
// (see Universal Serial Bus Specification Revision 2.0 5.12.4.2).
|
||||
// Feedback value will be sent at FB endpoint interval till it's changed.
|
||||
bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback);
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
|
||||
TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_copied);
|
||||
#endif
|
||||
|
||||
// Invoked when audio set interface request received
|
||||
TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request);
|
||||
|
||||
// Invoked when audio set interface request received which closes an EP
|
||||
TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request);
|
||||
|
||||
// Invoked when audio class specific set request received for an EP
|
||||
TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
|
||||
|
||||
// Invoked when audio class specific set request received for an interface
|
||||
TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
|
||||
|
||||
// Invoked when audio class specific set request received for an entity
|
||||
TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
|
||||
|
||||
// Invoked when audio class specific get request received for an EP
|
||||
TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request);
|
||||
|
||||
// Invoked when audio class specific get request received for an interface
|
||||
TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request);
|
||||
|
||||
// Invoked when audio class specific get request received for an entity
|
||||
TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Inline Functions
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
static inline bool tud_audio_mounted(void)
|
||||
{
|
||||
return tud_audio_n_mounted(0);
|
||||
}
|
||||
|
||||
#if CFG_TUD_AUDIO_EPSIZE_IN
|
||||
#if CFG_TUD_AUDIO_TX_FIFO_SIZE && CFG_TUD_AUDIO_TX_FIFO_COUNT > 1
|
||||
static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t n_bytes) // Short version if only one audio function is used
|
||||
{
|
||||
return tud_audio_n_write(0, channelId, buffer, n_bytes);
|
||||
}
|
||||
#else
|
||||
static inline uint16_t tud_audio_write (uint8_t const* buffer, uint16_t n_bytes) // Short version if only one audio function is used
|
||||
{
|
||||
return tud_audio_n_write(0, buffer, n_bytes);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline uint16_t tud_audio_write_flush (void) // Short version if only one audio function is used
|
||||
{
|
||||
#if CFG_TUD_AUDIO_TX_FIFO_SIZE
|
||||
return tud_audio_n_write_flush(0);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
|
||||
|
||||
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
|
||||
#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1
|
||||
static inline uint16_t tud_audio_available(uint8_t channelId)
|
||||
{
|
||||
return tud_audio_n_available(0, channelId);
|
||||
}
|
||||
|
||||
static inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize)
|
||||
{
|
||||
return tud_audio_n_read(0, channelId, buffer, bufsize);
|
||||
}
|
||||
|
||||
static inline void tud_audio_read_flush(uint8_t channelId)
|
||||
{
|
||||
tud_audio_n_read_flush(0, channelId);
|
||||
}
|
||||
#else
|
||||
static inline uint16_t tud_audio_available(void)
|
||||
{
|
||||
return tud_audio_n_available(0);
|
||||
}
|
||||
|
||||
static inline uint16_t tud_audio_read(void *buffer, uint16_t bufsize)
|
||||
{
|
||||
return tud_audio_n_read(0, buffer, bufsize);
|
||||
}
|
||||
|
||||
static inline void tud_audio_read_flush(void)
|
||||
{
|
||||
tud_audio_n_read_flush(0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0
|
||||
static inline uint16_t tud_audio_int_ctr_available(void)
|
||||
{
|
||||
return tud_audio_int_ctr_n_available(0);
|
||||
}
|
||||
|
||||
static inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize)
|
||||
{
|
||||
return tud_audio_int_ctr_n_read(0, buffer, bufsize);
|
||||
}
|
||||
|
||||
static inline void tud_audio_int_ctr_read_flush(void)
|
||||
{
|
||||
return tud_audio_int_ctr_n_read_flush(0);
|
||||
}
|
||||
|
||||
static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize)
|
||||
{
|
||||
return tud_audio_int_ctr_n_write(0, buffer, bufsize);
|
||||
}
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Class Driver API
|
||||
//--------------------------------------------------------------------+
|
||||
void audiod_init (void);
|
||||
void audiod_reset (uint8_t rhport);
|
||||
uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool audiod_control_request (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool audiod_control_complete (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_AUDIO_DEVICE_H_ */
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
@ -73,18 +73,29 @@ typedef struct
|
||||
//--------------------------------------------------------------------+
|
||||
CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
|
||||
|
||||
static void _prep_out_transaction (uint8_t itf)
|
||||
static void _prep_out_transaction (cdcd_interface_t* p_cdc)
|
||||
{
|
||||
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
|
||||
|
||||
// skip if previous transfer not complete
|
||||
if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_out) ) return;
|
||||
uint8_t const rhport = TUD_OPT_RHPORT;
|
||||
uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff);
|
||||
|
||||
// Prepare for incoming data but only allow what we can store in the ring buffer.
|
||||
uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff);
|
||||
if ( max_read >= sizeof(p_cdc->epout_buf) )
|
||||
// TODO Actually we can still carry out the transfer, keeping count of received bytes
|
||||
// and slowly move it to the FIFO when read().
|
||||
// This pre-check reduces endpoint claiming
|
||||
TU_VERIFY(available >= sizeof(p_cdc->epout_buf), );
|
||||
|
||||
// claim endpoint
|
||||
TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out), );
|
||||
|
||||
// fifo can be changed before endpoint is claimed
|
||||
available = tu_fifo_remaining(&p_cdc->rx_ff);
|
||||
|
||||
if ( available >= sizeof(p_cdc->epout_buf) ) {
|
||||
usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf));
|
||||
}else
|
||||
{
|
||||
usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf));
|
||||
// Release endpoint since we don't make any transfer
|
||||
usbd_edpt_release(rhport, p_cdc->ep_out);
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,8 +134,9 @@ uint32_t tud_cdc_n_available(uint8_t itf)
|
||||
|
||||
uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize)
|
||||
{
|
||||
uint32_t num_read = tu_fifo_read_n(&_cdcd_itf[itf].rx_ff, buffer, bufsize);
|
||||
_prep_out_transaction(itf);
|
||||
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
|
||||
uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, bufsize);
|
||||
_prep_out_transaction(p_cdc);
|
||||
return num_read;
|
||||
}
|
||||
|
||||
@ -135,8 +147,9 @@ bool tud_cdc_n_peek(uint8_t itf, int pos, uint8_t* chr)
|
||||
|
||||
void tud_cdc_n_read_flush (uint8_t itf)
|
||||
{
|
||||
tu_fifo_clear(&_cdcd_itf[itf].rx_ff);
|
||||
_prep_out_transaction(itf);
|
||||
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
|
||||
tu_fifo_clear(&p_cdc->rx_ff);
|
||||
_prep_out_transaction(p_cdc);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@ -144,11 +157,12 @@ void tud_cdc_n_read_flush (uint8_t itf)
|
||||
//--------------------------------------------------------------------+
|
||||
uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize)
|
||||
{
|
||||
uint16_t ret = tu_fifo_write_n(&_cdcd_itf[itf].tx_ff, buffer, bufsize);
|
||||
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
|
||||
uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, bufsize);
|
||||
|
||||
#if 0 // TODO issue with circuitpython's REPL
|
||||
// flush if queue more than endpoint size
|
||||
if ( tu_fifo_count(&_cdcd_itf[itf].tx_ff) >= CFG_TUD_CDC_EP_BUFSIZE )
|
||||
if ( tu_fifo_count(&p_cdc->tx_ff) >= CFG_TUD_CDC_EP_BUFSIZE )
|
||||
{
|
||||
tud_cdc_n_write_flush(itf);
|
||||
}
|
||||
@ -161,17 +175,28 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf)
|
||||
{
|
||||
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
|
||||
|
||||
// skip if previous transfer not complete yet
|
||||
TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in), 0 );
|
||||
// No data to send
|
||||
if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0;
|
||||
|
||||
uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf));
|
||||
if ( count )
|
||||
uint8_t const rhport = TUD_OPT_RHPORT;
|
||||
|
||||
// Claim the endpoint
|
||||
TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 );
|
||||
|
||||
// Pull data from FIFO
|
||||
uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf));
|
||||
|
||||
if ( count && tud_cdc_n_connected(itf) )
|
||||
{
|
||||
TU_VERIFY( tud_cdc_n_connected(itf), 0 ); // fifo is empty if not connected
|
||||
TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count), 0 );
|
||||
TU_ASSERT( usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 );
|
||||
return count;
|
||||
}else
|
||||
{
|
||||
// Release endpoint since we don't make any transfer
|
||||
// Note: data is dropped if terminal is not connected
|
||||
usbd_edpt_release(rhport, p_cdc->ep_in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
uint32_t tud_cdc_n_write_available (uint8_t itf)
|
||||
@ -194,7 +219,7 @@ void cdcd_init(void)
|
||||
p_cdc->wanted_char = -1;
|
||||
|
||||
// default line coding is : stop bit = 1, parity = none, data bits = 8
|
||||
p_cdc->line_coding.bit_rate = 115200;
|
||||
p_cdc->line_coding.bit_rate = 115200;
|
||||
p_cdc->line_coding.stop_bits = 0;
|
||||
p_cdc->line_coding.parity = 0;
|
||||
p_cdc->line_coding.data_bits = 8;
|
||||
@ -233,8 +258,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
|
||||
|
||||
// Find available interface
|
||||
cdcd_interface_t * p_cdc = NULL;
|
||||
uint8_t cdc_id;
|
||||
for(cdc_id=0; cdc_id<CFG_TUD_CDC; cdc_id++)
|
||||
for(uint8_t cdc_id=0; cdc_id<CFG_TUD_CDC; cdc_id++)
|
||||
{
|
||||
if ( _cdcd_itf[cdc_id].ep_in == 0 )
|
||||
{
|
||||
@ -283,7 +307,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
|
||||
}
|
||||
|
||||
// Prepare for incoming data
|
||||
_prep_out_transaction(cdc_id);
|
||||
_prep_out_transaction(p_cdc);
|
||||
|
||||
return drv_len;
|
||||
}
|
||||
@ -408,7 +432,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
|
||||
if (tud_cdc_rx_cb && tu_fifo_count(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf);
|
||||
|
||||
// prepare for OUT transaction
|
||||
_prep_out_transaction(itf);
|
||||
_prep_out_transaction(p_cdc);
|
||||
}
|
||||
|
||||
// Data sent to host, we continue to fetch from tx fifo to send.
|
||||
@ -421,12 +445,15 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
|
||||
|
||||
if ( 0 == tud_cdc_n_write_flush(itf) )
|
||||
{
|
||||
// There is no data left, a ZLP should be sent if
|
||||
// If there is no data left, a ZLP should be sent if
|
||||
// xferred_bytes is multiple of EP size and not zero
|
||||
// FIXME CFG_TUD_CDC_EP_BUFSIZE is not Endpoint packet size
|
||||
if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) )
|
||||
if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) )
|
||||
{
|
||||
usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0);
|
||||
if ( usbd_edpt_claim(rhport, p_cdc->ep_in) )
|
||||
{
|
||||
usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bu
|
||||
static inline
|
||||
uint32_t tud_cdc_n_write_char (uint8_t itf, char ch);
|
||||
|
||||
// Write a nul-terminated string
|
||||
// Write a null-terminated string
|
||||
static inline
|
||||
uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
@ -57,33 +57,34 @@ typedef struct
|
||||
CFG_TUSB_MEM_SECTION static hidd_interface_t _hidd_itf[CFG_TUD_HID];
|
||||
|
||||
/*------------- Helpers -------------*/
|
||||
static inline hidd_interface_t* get_interface_by_itfnum(uint8_t itf_num)
|
||||
static inline uint8_t get_index_by_itfnum(uint8_t itf_num)
|
||||
{
|
||||
for (uint8_t i=0; i < CFG_TUD_HID; i++ )
|
||||
{
|
||||
if ( itf_num == _hidd_itf[i].itf_num ) return &_hidd_itf[i];
|
||||
}
|
||||
for (uint8_t i=0; i < CFG_TUD_HID; i++ )
|
||||
{
|
||||
if ( itf_num == _hidd_itf[i].itf_num ) return i;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// APPLICATION API
|
||||
//--------------------------------------------------------------------+
|
||||
bool tud_hid_ready(void)
|
||||
bool tud_hid_n_ready(uint8_t itf)
|
||||
{
|
||||
uint8_t itf = 0;
|
||||
uint8_t const ep_in = _hidd_itf[itf].ep_in;
|
||||
return tud_ready() && (ep_in != 0) && usbd_edpt_ready(TUD_OPT_RHPORT, ep_in);
|
||||
return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in);
|
||||
}
|
||||
|
||||
bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len)
|
||||
bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len)
|
||||
{
|
||||
TU_VERIFY( tud_hid_ready() );
|
||||
|
||||
uint8_t itf = 0;
|
||||
uint8_t const rhport = 0;
|
||||
hidd_interface_t * p_hid = &_hidd_itf[itf];
|
||||
|
||||
// claim endpoint
|
||||
TU_VERIFY( usbd_edpt_claim(rhport, p_hid->ep_in) );
|
||||
|
||||
// prepare data
|
||||
if (report_id)
|
||||
{
|
||||
len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE-1);
|
||||
@ -101,16 +102,15 @@ bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len)
|
||||
return usbd_edpt_xfer(TUD_OPT_RHPORT, p_hid->ep_in, p_hid->epin_buf, len);
|
||||
}
|
||||
|
||||
bool tud_hid_boot_mode(void)
|
||||
bool tud_hid_n_boot_mode(uint8_t itf)
|
||||
{
|
||||
uint8_t itf = 0;
|
||||
return _hidd_itf[itf].boot_mode;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// KEYBOARD API
|
||||
//--------------------------------------------------------------------+
|
||||
bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6])
|
||||
bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6])
|
||||
{
|
||||
hid_keyboard_report_t report;
|
||||
|
||||
@ -124,13 +124,13 @@ bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycod
|
||||
tu_memclr(report.keycode, 6);
|
||||
}
|
||||
|
||||
return tud_hid_report(report_id, &report, sizeof(report));
|
||||
return tud_hid_n_report(itf, report_id, &report, sizeof(report));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MOUSE APPLICATION API
|
||||
//--------------------------------------------------------------------+
|
||||
bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal)
|
||||
bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal)
|
||||
{
|
||||
hid_mouse_report_t report =
|
||||
{
|
||||
@ -141,7 +141,7 @@ bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y
|
||||
.pan = horizontal
|
||||
};
|
||||
|
||||
return tud_hid_report(report_id, &report, sizeof(report));
|
||||
return tud_hid_n_report(itf, report_id, &report, sizeof(report));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@ -194,7 +194,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1
|
||||
|
||||
p_hid->boot_mode = false; // default mode is REPORT
|
||||
p_hid->itf_num = desc_itf->bInterfaceNumber;
|
||||
|
||||
|
||||
// Use offsetof to avoid pointer to the odd/misaligned address
|
||||
memcpy(&p_hid->report_desc_len, (uint8_t*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength), 2);
|
||||
|
||||
@ -217,8 +217,10 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request
|
||||
{
|
||||
TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
|
||||
|
||||
hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) request->wIndex );
|
||||
TU_ASSERT(p_hid);
|
||||
uint8_t const hid_itf = get_index_by_itfnum((uint8_t) request->wIndex);
|
||||
TU_VERIFY(hid_itf < CFG_TUD_HID);
|
||||
|
||||
hidd_interface_t* p_hid = &_hidd_itf[hid_itf];
|
||||
|
||||
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD)
|
||||
{
|
||||
@ -234,7 +236,11 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request
|
||||
}
|
||||
else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT)
|
||||
{
|
||||
uint8_t const * desc_report = tud_hid_descriptor_report_cb();
|
||||
uint8_t const * desc_report = tud_hid_descriptor_report_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
hid_itf // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
);
|
||||
tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len);
|
||||
}
|
||||
else
|
||||
@ -253,7 +259,12 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request
|
||||
uint8_t const report_type = tu_u16_high(request->wValue);
|
||||
uint8_t const report_id = tu_u16_low(request->wValue);
|
||||
|
||||
uint16_t xferlen = tud_hid_get_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength);
|
||||
uint16_t xferlen = tud_hid_get_report_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
hid_itf, // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength
|
||||
);
|
||||
TU_ASSERT( xferlen > 0 );
|
||||
|
||||
tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen);
|
||||
@ -270,7 +281,12 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request
|
||||
if ( tud_hid_set_idle_cb )
|
||||
{
|
||||
// stall request if callback return false
|
||||
if ( !tud_hid_set_idle_cb(p_hid->idle_rate) ) return false;
|
||||
TU_VERIFY( tud_hid_set_idle_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
hid_itf, // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
p_hid->idle_rate)
|
||||
);
|
||||
}
|
||||
|
||||
tud_control_status(rhport, request);
|
||||
@ -291,7 +307,15 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request
|
||||
case HID_REQ_CONTROL_SET_PROTOCOL:
|
||||
p_hid->boot_mode = 1 - request->wValue; // 0 is Boot, 1 is Report protocol
|
||||
|
||||
if (tud_hid_boot_mode_cb) tud_hid_boot_mode_cb(p_hid->boot_mode);
|
||||
if (tud_hid_boot_mode_cb)
|
||||
{
|
||||
tud_hid_boot_mode_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
hid_itf, // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
p_hid->boot_mode
|
||||
);
|
||||
}
|
||||
|
||||
tud_control_status(rhport, request);
|
||||
break;
|
||||
@ -311,8 +335,11 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request
|
||||
bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_request)
|
||||
{
|
||||
(void) rhport;
|
||||
hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) p_request->wIndex );
|
||||
TU_ASSERT(p_hid);
|
||||
|
||||
uint8_t const hid_itf = get_index_by_itfnum((uint8_t) p_request->wIndex);
|
||||
TU_VERIFY(hid_itf < CFG_TUD_HID);
|
||||
|
||||
hidd_interface_t* p_hid = &_hidd_itf[hid_itf];
|
||||
|
||||
if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
|
||||
p_request->bRequest == HID_REQ_CONTROL_SET_REPORT)
|
||||
@ -321,7 +348,12 @@ bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_requ
|
||||
uint8_t const report_type = tu_u16_high(p_request->wValue);
|
||||
uint8_t const report_id = tu_u16_low(p_request->wValue);
|
||||
|
||||
tud_hid_set_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength);
|
||||
tud_hid_set_report_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
hid_itf, // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -343,7 +375,12 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
|
||||
|
||||
if (ep_addr == p_hid->ep_out)
|
||||
{
|
||||
tud_hid_set_report_cb(0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes);
|
||||
tud_hid_set_report_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
itf, // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes
|
||||
);
|
||||
TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)));
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
@ -50,51 +50,104 @@
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Application API
|
||||
// Application API (Multiple Ports)
|
||||
// CFG_TUD_HID > 1
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Check if the interface is ready to use
|
||||
bool tud_hid_ready(void);
|
||||
bool tud_hid_n_ready(uint8_t itf);
|
||||
|
||||
// Check if current mode is Boot (true) or Report (false)
|
||||
bool tud_hid_boot_mode(void);
|
||||
bool tud_hid_n_boot_mode(uint8_t itf);
|
||||
|
||||
// Send report to host
|
||||
bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len);
|
||||
bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len);
|
||||
|
||||
// KEYBOARD: convenient helper to send keyboard report if application
|
||||
// use template layout report as defined by hid_keyboard_report_t
|
||||
bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]);
|
||||
bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]);
|
||||
|
||||
// MOUSE: convenient helper to send mouse report if application
|
||||
// use template layout report as defined by hid_mouse_report_t
|
||||
bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal);
|
||||
bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Application API (Single Port)
|
||||
//--------------------------------------------------------------------+
|
||||
static inline bool tud_hid_ready(void);
|
||||
static inline bool tud_hid_boot_mode(void);
|
||||
static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len);
|
||||
static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]);
|
||||
static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Callbacks (Weak is optional)
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#if CFG_TUD_HID > 1
|
||||
|
||||
// Invoked when received GET HID REPORT DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
uint8_t const * tud_hid_descriptor_report_cb(void);
|
||||
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf);
|
||||
|
||||
// Invoked when received GET_REPORT control request
|
||||
// Application must fill buffer report's content and return its length.
|
||||
// Return zero will cause the stack to STALL request
|
||||
uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen);
|
||||
uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen);
|
||||
|
||||
// Invoked when received SET_REPORT control request or
|
||||
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
|
||||
void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize);
|
||||
void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize);
|
||||
|
||||
// Invoked when received SET_PROTOCOL request ( mode switch Boot <-> Report )
|
||||
TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode);
|
||||
TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t itf, uint8_t boot_mode);
|
||||
|
||||
// Invoked when received SET_IDLE request. return false will stall the request
|
||||
// - Idle Rate = 0 : only send report if there is changes, i.e skip duplication
|
||||
// - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms).
|
||||
TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t itf, uint8_t idle_rate);
|
||||
|
||||
#else
|
||||
|
||||
// TODO for backward compatible callback, remove later when appropriate
|
||||
uint8_t const * tud_hid_descriptor_report_cb(void);
|
||||
uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen);
|
||||
void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize);
|
||||
|
||||
TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode);
|
||||
TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Inline Functions
|
||||
//--------------------------------------------------------------------+
|
||||
static inline bool tud_hid_ready(void)
|
||||
{
|
||||
return tud_hid_n_ready(0);
|
||||
}
|
||||
|
||||
static inline bool tud_hid_boot_mode(void)
|
||||
{
|
||||
return tud_hid_n_boot_mode(0);
|
||||
}
|
||||
|
||||
static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len)
|
||||
{
|
||||
return tud_hid_n_report(0, report_id, report, len);
|
||||
}
|
||||
|
||||
static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6])
|
||||
{
|
||||
return tud_hid_n_keyboard_report(0, report_id, modifier, keycode);
|
||||
}
|
||||
|
||||
static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal)
|
||||
{
|
||||
return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------+
|
||||
* HID Report Descriptor Template
|
||||
*
|
||||
@ -264,7 +317,7 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate);
|
||||
HID_LOGICAL_MAX ( 1 ) ,\
|
||||
HID_REPORT_COUNT ( 16 ) ,\
|
||||
HID_REPORT_SIZE ( 1 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
|
||||
/* X, Y, Z, Rz (min -127, max 127 ) */ \
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
|
||||
HID_LOGICAL_MIN ( 0x81 ) ,\
|
||||
@ -318,4 +371,3 @@ bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t e
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_HID_DEVICE_H_ */
|
||||
|
||||
|
@ -153,15 +153,25 @@ void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bu
|
||||
|
||||
static uint32_t write_flush(midid_interface_t* midi)
|
||||
{
|
||||
// No data to send
|
||||
if ( !tu_fifo_count(&midi->tx_ff) ) return 0;
|
||||
|
||||
uint8_t const rhport = TUD_OPT_RHPORT;
|
||||
|
||||
// skip if previous transfer not complete
|
||||
TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, midi->ep_in) );
|
||||
TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 );
|
||||
|
||||
uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE);
|
||||
if (count > 0)
|
||||
{
|
||||
TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, midi->ep_in, midi->epin_buf, count) );
|
||||
TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, midi->epin_buf, count), 0 );
|
||||
return count;
|
||||
}else
|
||||
{
|
||||
// Release endpoint since we don't make any transfer
|
||||
usbd_edpt_release(rhport, midi->ep_in);
|
||||
return 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize)
|
||||
@ -183,7 +193,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u
|
||||
if (data == 0xf7) {
|
||||
midi->write_buffer[0] = 0x5;
|
||||
} else {
|
||||
midi->write_buffer_length = 4;
|
||||
midi->write_target_length = 4;
|
||||
}
|
||||
} else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) {
|
||||
midi->write_buffer[0] = jack_id << 4 | msg;
|
||||
@ -290,9 +300,9 @@ void midid_reset(uint8_t rhport)
|
||||
uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len)
|
||||
{
|
||||
// 1st Interface is Audio Control v1
|
||||
TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass &&
|
||||
AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass &&
|
||||
AUDIO_PROTOCOL_V1 == desc_itf->bInterfaceProtocol, 0);
|
||||
TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass &&
|
||||
AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass &&
|
||||
AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0);
|
||||
|
||||
uint16_t drv_len = tu_desc_len(desc_itf);
|
||||
uint8_t const * p_desc = tu_desc_next(desc_itf);
|
||||
@ -308,9 +318,9 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint
|
||||
TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0);
|
||||
tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc;
|
||||
|
||||
TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass &&
|
||||
AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass &&
|
||||
AUDIO_PROTOCOL_V1 == desc_midi->bInterfaceProtocol, 0);
|
||||
TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass &&
|
||||
AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass &&
|
||||
AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0);
|
||||
|
||||
// Find available interface
|
||||
midid_interface_t * p_midi = NULL;
|
||||
@ -405,17 +415,22 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32
|
||||
if (tud_midi_rx_cb) tud_midi_rx_cb(itf);
|
||||
|
||||
// prepare for next
|
||||
// TODO for now ep_out is not used by public API therefore there is no race condition,
|
||||
// and does not need to claim like ep_in
|
||||
TU_ASSERT(usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE), false);
|
||||
}
|
||||
else if ( ep_addr == p_midi->ep_in )
|
||||
{
|
||||
if (0 == write_flush(p_midi))
|
||||
{
|
||||
// There is no data left, a ZLP should be sent if
|
||||
// If there is no data left, a ZLP should be sent if
|
||||
// xferred_bytes is multiple of EP size and not zero
|
||||
if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) )
|
||||
if ( !tu_fifo_count(&p_midi->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) )
|
||||
{
|
||||
usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0);
|
||||
if ( usbd_edpt_claim(rhport, p_midi->ep_in) )
|
||||
{
|
||||
usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,10 +47,10 @@
|
||||
#define U16_TO_U8S_BE(u16) TU_U16_HIGH(u16), TU_U16_LOW(u16)
|
||||
#define U16_TO_U8S_LE(u16) TU_U16_LOW(u16), TU_U16_HIGH(u16)
|
||||
|
||||
#define U32_B1_U8(u32) ((uint8_t) (((u32) >> 24) & 0x000000ff)) // MSB
|
||||
#define U32_B2_U8(u32) ((uint8_t) (((u32) >> 16) & 0x000000ff))
|
||||
#define U32_B3_U8(u32) ((uint8_t) (((u32) >> 8) & 0x000000ff))
|
||||
#define U32_B4_U8(u32) ((uint8_t) ((u32) & 0x000000ff)) // LSB
|
||||
#define U32_B1_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 24) & 0x000000ff)) // MSB
|
||||
#define U32_B2_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 16) & 0x000000ff))
|
||||
#define U32_B3_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 8) & 0x000000ff))
|
||||
#define U32_B4_U8(u32) ((uint8_t) (((uint32_t) u32) & 0x000000ff)) // LSB
|
||||
|
||||
#define U32_TO_U8S_BE(u32) U32_B1_U8(u32), U32_B2_U8(u32), U32_B3_U8(u32), U32_B4_U8(u32)
|
||||
#define U32_TO_U8S_LE(u32) U32_B4_U8(u32), U32_B3_U8(u32), U32_B2_U8(u32), U32_B1_U8(u32)
|
||||
|
@ -44,8 +44,10 @@
|
||||
#endif
|
||||
|
||||
// Compile-time Assert
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||
#define TU_VERIFY_STATIC _Static_assert
|
||||
#elif defined (__cplusplus) && __cplusplus >= 201103L
|
||||
#define TU_VERIFY_STATIC static_assert
|
||||
#else
|
||||
#define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) }
|
||||
#endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user