update
This commit is contained in:
@@ -225,6 +225,8 @@ sequenceDiagram
|
||||
| 0x24 | XU316 send playback volume | XU316→MCU |
|
||||
| 0x25 | Send recording volume | XU316→MCU |
|
||||
| 0x26 | Switch MCLK | MCU→XU316 |
|
||||
| 0x27 | Set unmute | MCU→XU316 |
|
||||
| 0x28 | Send audio format time delay | MCU→XU316 |
|
||||
| 0x29 | Report USB connection status | XU316→MCU |
|
||||
|
||||
=== "HID-MCU Passthrough Commands (0xEE-0xEF)"
|
||||
@@ -237,6 +239,7 @@ sequenceDiagram
|
||||
| Command | Command Description | Direction |
|
||||
|:--------:|:---------------------------------------------|:----------:|
|
||||
| 0xF0 | DAC configuration selection command | MCU→XU316 |
|
||||
| 0xF1 | Get firmware version command | MCU→XU316 |
|
||||
|
||||
!!! note "Command Usage Instructions"
|
||||
1. All commands must follow basic frame format specification
|
||||
@@ -307,6 +310,24 @@ sequenceDiagram
|
||||
* Restart reason field can be used by MCU to identify specific reason for XU316 restart for different handling
|
||||
* When multiple info items need updating, MCU can combine multiple options through bit operations
|
||||
|
||||
=== "MCU Return Example"
|
||||
|
||||
**Command Example**
|
||||
```
|
||||
55 AA 03 00 01 03 06
|
||||
```
|
||||
|
||||
**Field Breakdown**
|
||||
|
||||
| Byte Segment | Length | Example | Description |
|
||||
|:-------|:-----|:-------|:-----|
|
||||
| Frame Header | 2 bytes | `55 AA` | Fixed frame header indicating start of a protocol frame |
|
||||
| Version | 1 byte | `03` | Indicates this frame is returned by MCU to XU316 |
|
||||
| Command | 1 byte | `00` | Current command is “Start-up” |
|
||||
| Data Length | 1 byte | `01` | One data byte follows |
|
||||
| Startup options | 1 byte | `03` | `0x01` + `0x02` are both set: update basic product info and power-on config info |
|
||||
| Checksum | 1 byte | `06` | Sum of all bytes from `55` to `03`, modulo 256 |
|
||||
|
||||
#### 3.2.2 Read Product Info (0x01)
|
||||
|
||||
=== "Command Format"
|
||||
@@ -348,6 +369,31 @@ sequenceDiagram
|
||||
CRC: 4 bytes (32-bit CRC checksum)
|
||||
```
|
||||
|
||||
=== "MCU Return Example"
|
||||
|
||||
**Command Example**
|
||||
```
|
||||
55 AA 03 01 3C 20 B1 00 17 20 B1 00 16 50 48 41 54 45 4E 00 00 00 00 00 00 00 00 00 00 58 55 33 31 36 20 44 41 43 00 00 00 00 00 00 00 53 4E 32 34 30 30 30 31 00 00 00 00 00 00 00 00 12 34 56 78 D9
|
||||
```
|
||||
|
||||
**Field Breakdown**
|
||||
|
||||
| Byte Segment | Length | Example | Description |
|
||||
|:-------|:-----|:-------|:-----|
|
||||
| Frame Header | 2 bytes | `55 AA` | Fixed frame header indicating start of a protocol frame |
|
||||
| Version | 1 byte | `03` | Indicates this frame is returned by MCU to XU316 |
|
||||
| Command | 1 byte | `01` | Current command is “Read Product Info” |
|
||||
| Data Length | 1 byte | `3C` | 60 data bytes follow |
|
||||
| VID1 | 2 bytes | `20 B1` | USB VID for UAC1.0 |
|
||||
| PID1 | 2 bytes | `00 17` | USB PID for UAC1.0 |
|
||||
| VID2 | 2 bytes | `20 B1` | USB VID for UAC2.0 |
|
||||
| PID2 | 2 bytes | `00 16` | USB PID for UAC2.0 |
|
||||
| ManufactureName | 16 bytes | `50 48 41 54 45 4E 00 00 00 00 00 00 00 00 00 00` | ASCII string `PHATEN`, padded with `00` to 16 bytes |
|
||||
| ProductName | 16 bytes | `58 55 33 31 36 20 44 41 43 00 00 00 00 00 00 00` | ASCII string `XU316 DAC`, padded with `00` to 16 bytes |
|
||||
| SerialNumber | 16 bytes | `53 4E 32 34 30 30 30 31 00 00 00 00 00 00 00 00` | ASCII string `SN240001`, padded with `00` to 16 bytes |
|
||||
| CRC | 4 bytes | `12 34 56 78` | 32-bit CRC for product basic info (example only) |
|
||||
| Checksum | 1 byte | `D9` | Sum of all bytes from `55` to `78`, modulo 256 |
|
||||
|
||||
#### 3.2.3 Read Power-On Config Info (0x02)
|
||||
|
||||
=== "Command Format"
|
||||
@@ -387,6 +433,29 @@ sequenceDiagram
|
||||
CRC: 4 bytes (32-bit CRC checksum)
|
||||
```
|
||||
|
||||
=== "MCU Return Example"
|
||||
|
||||
**Command Example**
|
||||
```
|
||||
55 AA 03 02 0E 01 00 00 00 00 01 2C 20 30 30 11 22 33 44 6A
|
||||
```
|
||||
|
||||
**Field Breakdown**
|
||||
|
||||
| Byte Segment | Length | Example | Description |
|
||||
|:-------|:-----|:-------|:-----|
|
||||
| Frame Header | 2 bytes | `55 AA` | Fixed frame header indicating start of a protocol frame |
|
||||
| Version | 1 byte | `03` | Indicates this frame is returned by MCU to XU316 |
|
||||
| Command | 1 byte | `02` | Current command is “Read Power-On Config Info” |
|
||||
| Data Length | 1 byte | `0E` | 14 data bytes follow |
|
||||
| Default input/output mode | 5 bytes | `01 00 00 00 00` | Example mode data; each byte definition depends on product specification |
|
||||
| Mute time | 2 bytes | `01 2C` | `300ms` in big-endian encoding |
|
||||
| Microphone default volume | 1 byte | `20` | Example default microphone volume |
|
||||
| DAC left channel default volume | 1 byte | `30` | Example default left channel volume |
|
||||
| DAC right channel default volume | 1 byte | `30` | Example default right channel volume |
|
||||
| CRC | 4 bytes | `11 22 33 44` | 32-bit CRC for power-on config (example only) |
|
||||
| Checksum | 1 byte | `6A` | Sum of all bytes from `55` to `44`, modulo 256 |
|
||||
|
||||
#### 3.2.4 Get Current Input/Output Mode (0x03)
|
||||
|
||||
=== "Command Format"
|
||||
@@ -415,6 +484,24 @@ sequenceDiagram
|
||||
- XU316 will load corresponding application firmware based on returned mode
|
||||
- This command is used for mode matching and confirmation during device startup
|
||||
|
||||
=== "MCU Return Example"
|
||||
|
||||
**Command Example**
|
||||
```
|
||||
55 AA 03 03 05 01 00 00 00 00 0B
|
||||
```
|
||||
|
||||
**Field Breakdown**
|
||||
|
||||
| Byte Segment | Length | Example | Description |
|
||||
|:-------|:-----|:-------|:-----|
|
||||
| Frame Header | 2 bytes | `55 AA` | Fixed frame header indicating start of a protocol frame |
|
||||
| Version | 1 byte | `03` | Indicates this frame is returned by MCU to XU316 |
|
||||
| Command | 1 byte | `03` | Current command is “Get Current Input/Output Mode” |
|
||||
| Data Length | 1 byte | `05` | 5 data bytes follow |
|
||||
| Input/output mode | 5 bytes | `01 00 00 00 00` | Example mode data; definitions depend on product specification |
|
||||
| Checksum | 1 byte | `0B` | Sum of all bytes from `55` to the last mode byte, modulo 256 |
|
||||
|
||||
#### 3.2.5 Get Current User Configuration (0x04)
|
||||
|
||||
=== "Command Format"
|
||||
@@ -443,6 +530,29 @@ sequenceDiagram
|
||||
- Executed after application firmware loaded, before application startup
|
||||
- Application will initialize corresponding parameters based on returned info
|
||||
|
||||
=== "MCU Return Example"
|
||||
|
||||
**Command Example**
|
||||
```
|
||||
55 AA 03 04 0E 02 00 00 00 00 00 C8 18 28 28 55 66 77 88 00
|
||||
```
|
||||
|
||||
**Field Breakdown**
|
||||
|
||||
| Byte Segment | Length | Example | Description |
|
||||
|:-------|:-----|:-------|:-----|
|
||||
| Frame Header | 2 bytes | `55 AA` | Fixed frame header indicating start of a protocol frame |
|
||||
| Version | 1 byte | `03` | Indicates this frame is returned by MCU to XU316 |
|
||||
| Command | 1 byte | `04` | Current command is “Get Current User Configuration” |
|
||||
| Data Length | 1 byte | `0E` | 14 data bytes follow |
|
||||
| Input/output mode | 5 bytes | `02 00 00 00 00` | Example current user-selected mode data; definitions depend on product specification |
|
||||
| Mute time | 2 bytes | `00 C8` | `200ms` in big-endian encoding |
|
||||
| Microphone volume | 1 byte | `18` | Example current microphone volume |
|
||||
| DAC left channel volume | 1 byte | `28` | Example current left channel volume |
|
||||
| DAC right channel volume | 1 byte | `28` | Example current right channel volume |
|
||||
| CRC | 4 bytes | `55 66 77 88` | 32-bit CRC for user configuration (example only) |
|
||||
| Checksum | 1 byte | `00` | Sum of all bytes from `55` to `88`, modulo 256 |
|
||||
|
||||
#### 3.2.6 Startup Complete Command (0x05)
|
||||
|
||||
=== "Command Format"
|
||||
@@ -473,6 +583,23 @@ sequenceDiagram
|
||||
- Contains startup status info to notify MCU if startup succeeded or encountered problems
|
||||
- All subsequent business commands can only be used after this command is successfully sent
|
||||
|
||||
=== "MCU Return Example"
|
||||
|
||||
**Command Example**
|
||||
```
|
||||
55 AA 03 05 00 07
|
||||
```
|
||||
|
||||
**Field Breakdown**
|
||||
|
||||
| Byte Segment | Length | Example | Description |
|
||||
|:-------|:-----|:-------|:-----|
|
||||
| Frame Header | 2 bytes | `55 AA` | Fixed frame header indicating start of a protocol frame |
|
||||
| Version | 1 byte | `03` | Indicates this frame is an acknowledgment returned by MCU to XU316 |
|
||||
| Command | 1 byte | `05` | Acknowledges “Startup Complete Command” |
|
||||
| Data Length | 1 byte | `00` | Pure acknowledgment frame with no data |
|
||||
| Checksum | 1 byte | `07` | Sum of all bytes from `55` to `00`, modulo 256 |
|
||||
|
||||
### 3.3 Business Control Command Details
|
||||
|
||||
!!! warning "Usage Prerequisites"
|
||||
@@ -506,6 +633,23 @@ sequenceDiagram
|
||||
- Typically sent when status changes, such as volume change, mode switch, etc.
|
||||
- MCU can update UI display or adjust related functions based on this info
|
||||
|
||||
=== "MCU Return Example"
|
||||
|
||||
**Command Example**
|
||||
```
|
||||
55 AA 03 20 00 22
|
||||
```
|
||||
|
||||
**Field Breakdown**
|
||||
|
||||
| Byte Segment | Length | Example | Description |
|
||||
|:-------|:-----|:-------|:-----|
|
||||
| Frame Header | 2 bytes | `55 AA` | Fixed frame header indicating start of a protocol frame |
|
||||
| Version | 1 byte | `03` | Indicates this frame is an acknowledgment returned by MCU to XU316 |
|
||||
| Command | 1 byte | `20` | Acknowledges “Report Application Status” |
|
||||
| Data Length | 1 byte | `00` | Pure acknowledgment frame with no data |
|
||||
| Checksum | 1 byte | `22` | Sum of all bytes from `55` to `00`, modulo 256 |
|
||||
|
||||
#### 3.3.2 Media Control (0x21)
|
||||
|
||||
=== "Command Format"
|
||||
@@ -582,6 +726,23 @@ sequenceDiagram
|
||||
- Typically sent when playback starts or format changes
|
||||
- MCU can update display based on this info, such as showing PCM/DSD/MQA/DOP status
|
||||
|
||||
=== "MCU Return Example"
|
||||
|
||||
**Command Example**
|
||||
```
|
||||
55 AA 03 22 00 24
|
||||
```
|
||||
|
||||
**Field Breakdown**
|
||||
|
||||
| Byte Segment | Length | Example | Description |
|
||||
|:-------|:-----|:-------|:-----|
|
||||
| Frame Header | 2 bytes | `55 AA` | Fixed frame header indicating start of a protocol frame |
|
||||
| Version | 1 byte | `03` | Indicates this frame is an acknowledgment returned by MCU to XU316 |
|
||||
| Command | 1 byte | `22` | Acknowledges “Report Playback Audio Stream Format and Type” |
|
||||
| Data Length | 1 byte | `00` | Pure acknowledgment frame with no data |
|
||||
| Checksum | 1 byte | `24` | Sum of all bytes from `55` to `00`, modulo 256 |
|
||||
|
||||
#### 3.3.4 Set Input/Output Mode (0x23)
|
||||
|
||||
=== "Command Format"
|
||||
@@ -638,6 +799,23 @@ sequenceDiagram
|
||||
=== "Function Description"
|
||||
- This command is used by XU316 to report current playback volume to MCU
|
||||
|
||||
=== "MCU Return Example"
|
||||
|
||||
**Command Example**
|
||||
```
|
||||
55 AA 03 24 00 26
|
||||
```
|
||||
|
||||
**Field Breakdown**
|
||||
|
||||
| Byte Segment | Length | Example | Description |
|
||||
|:-------|:-----|:-------|:-----|
|
||||
| Frame Header | 2 bytes | `55 AA` | Fixed frame header indicating start of a protocol frame |
|
||||
| Version | 1 byte | `03` | Indicates this frame is an acknowledgment returned by MCU to XU316 |
|
||||
| Command | 1 byte | `24` | Acknowledges “Send Playback Volume” |
|
||||
| Data Length | 1 byte | `00` | Pure acknowledgment frame with no data |
|
||||
| Checksum | 1 byte | `26` | Sum of all bytes from `55` to `00`, modulo 256 |
|
||||
|
||||
|
||||
#### 3.3.6 Send Recording Volume (0x25)
|
||||
|
||||
@@ -666,6 +844,23 @@ sequenceDiagram
|
||||
- This command is used by XU316 to report current microphone recording volume to MCU
|
||||
- Reserved command, currently not used
|
||||
|
||||
=== "MCU Return Example"
|
||||
|
||||
**Command Example**
|
||||
```
|
||||
55 AA 03 25 00 27
|
||||
```
|
||||
|
||||
**Field Breakdown**
|
||||
|
||||
| Byte Segment | Length | Example | Description |
|
||||
|:-------|:-----|:-------|:-----|
|
||||
| Frame Header | 2 bytes | `55 AA` | Fixed frame header indicating start of a protocol frame |
|
||||
| Version | 1 byte | `03` | Indicates this frame is an acknowledgment returned by MCU to XU316 |
|
||||
| Command | 1 byte | `25` | Acknowledges “Send Recording Volume” |
|
||||
| Data Length | 1 byte | `00` | Pure acknowledgment frame with no data |
|
||||
| Checksum | 1 byte | `27` | Sum of all bytes from `55` to `00`, modulo 256 |
|
||||
|
||||
#### 3.3.7 Switch MCLK (0x26)
|
||||
|
||||
=== "Command Format"
|
||||
@@ -776,6 +971,23 @@ sequenceDiagram
|
||||
- When the USB connection status changes (connect or disconnect), XU316 proactively sends this command
|
||||
- The MCU can use this information to update the UI or adjust related functions
|
||||
|
||||
=== "MCU Return Example"
|
||||
|
||||
**Command Example**
|
||||
```
|
||||
55 AA 03 29 00 2B
|
||||
```
|
||||
|
||||
**Field Breakdown**
|
||||
|
||||
| Byte Segment | Length | Example | Description |
|
||||
|:-------|:-----|:-------|:-----|
|
||||
| Frame Header | 2 bytes | `55 AA` | Fixed frame header indicating start of a protocol frame |
|
||||
| Version | 1 byte | `03` | Indicates this frame is an acknowledgment returned by MCU to XU316 |
|
||||
| Command | 1 byte | `29` | Acknowledges “Report USB Connection Status” |
|
||||
| Data Length | 1 byte | `00` | Pure acknowledgment frame with no data |
|
||||
| Checksum | 1 byte | `2B` | Sum of all bytes from `55` to `00`, modulo 256 |
|
||||
|
||||
#### 3.3.11 Get Firmware Version Command (0xF1)
|
||||
|
||||
=== "Command Format"
|
||||
|
||||
@@ -1,286 +0,0 @@
|
||||
---
|
||||
title: XU316-MCU Communication Protocol Command Macro Definitions
|
||||
description: This document provides command macro definitions for the XU316-MCU communication protocol, including frame formats, command lengths, communication protocols, and more to help developers implement XU316-MCU communication functionality.
|
||||
keywords: XU316 communication protocol, MCU command macros, audio format definitions, communication frame format, command data structures, audio type definitions
|
||||
---
|
||||
|
||||
--8<-- "common/phaten_xmos_support_img.md"
|
||||
|
||||
# XU316-MCU Communication Protocol Command Macro Definitions
|
||||
|
||||
## Document Overview
|
||||
|
||||
This document provides command macro definitions for the XU316-MCU communication protocol, including:
|
||||
|
||||
1. Communication frame format definitions
|
||||
2. MCU command data length definitions
|
||||
3. Communication protocol command word enumerations
|
||||
4. Audio format and type definitions
|
||||
5. Command data structure definitions
|
||||
|
||||
These macro definitions and data structures are the foundation of XU316-MCU communication. Developers need to correctly understand and use these definitions to implement communication functionality.
|
||||
|
||||
## Communication Frame Format
|
||||
|
||||
### Basic Frame Format Definitions
|
||||
```c
|
||||
#define FRAME_HEADER_H 0x55
|
||||
#define FRAME_HEADER_L 0xAA
|
||||
#define PROTOCOL_VERSION 0x01
|
||||
#define PROTOCOL_VERSION_RX 0x03
|
||||
```
|
||||
|
||||
## Command Data Length Definitions
|
||||
|
||||
### XU316 Command Data Length
|
||||
```c
|
||||
#define CMD00_XU316_DATA_LEN 0x11 // 0x00 Command: Start boot (boot options)
|
||||
#define CMD01_XU316_DATA_LEN 0x00 // 0x01 Command: Read product information (60-byte firmware info)
|
||||
#define CMD02_XU316_DATA_LEN 0x00 // 0x02 Command: Read power-on configuration (14-byte config parameters)
|
||||
#define CMD03_XU316_DATA_LEN 0x00 // 0x03 Command: Get audio mode (5-byte mode parameters)
|
||||
#define CMD04_XU316_DATA_LEN 0x00 // 0x04 Command: Get user configuration (14-byte user settings)
|
||||
#define CMD05_XU316_DATA_LEN 0x15 // 0x05 Command: Boot complete (no data field)
|
||||
|
||||
#define CMDF1_XU316_DATA_LEN 0x03 // 0xF1 Command: Version query (3-byte version info)
|
||||
|
||||
#define CMD20_XU316_DATA_LEN 0x14 // 0x20 Command: Set volume
|
||||
#define CMD21_XU316_DATA_LEN 0x00 // 0x21 Command: Audio effect mode
|
||||
#define CMD22_XU316_DATA_LEN 0x02 // 0x22 Command: Device status query
|
||||
#define CMD23_XU316_DATA_LEN 0x00 // 0x23 Command: Bluetooth control
|
||||
#define CMD24_XU316_DATA_LEN 0x02 // 0x24 Command: Send playback volume
|
||||
#define CMD25_XU316_DATA_LEN 0x01 // 0x25 Command: Send recording volume
|
||||
#define CMD27_XU316_DATA_LEN 0x00 // 0x27 Command: Special unmute (no data field)
|
||||
#define CMD28_XU316_DATA_LEN 0x01 // 0x28 Command: Audio format delay setting (1-byte parameter)
|
||||
|
||||
#define CMD_HID_TRANSPARENT_DATA_LEN 0x39 // 0xEE Command: HID transparent/OTA upgrade (57 bytes)
|
||||
```
|
||||
|
||||
### MCU Command Data Length
|
||||
```c
|
||||
#define CMD00_MCU_DATA_LEN 0x01 // 0x00 Command: Start boot (boot options)
|
||||
#define CMD01_MCU_DATA_LEN 0x3C // 0x01 Command: Read product information (60-byte firmware info)
|
||||
#define CMD02_MCU_DATA_LEN 0x0E // 0x02 Command: Read power-on configuration (14-byte config parameters)
|
||||
#define CMD03_MCU_DATA_LEN 0x05 // 0x03 Command: Get audio mode (5-byte mode parameters)
|
||||
#define CMD04_MCU_DATA_LEN 0x0E // 0x04 Command: Get user configuration (14-byte user settings)
|
||||
#define CMD05_MCU_DATA_LEN 0x00 // 0x05 Command: Boot complete (no data field)
|
||||
|
||||
#define CMDF1_MCU_DATA_LEN 0x00 // 0xF1 Command: Version query (no data field)
|
||||
|
||||
#define CMD20_MCU_DATA_LEN 0x00 // 0x20 Command: Set volume
|
||||
#define CMD21_MCU_DATA_LEN 0x01 // 0x21 Command: Audio effect mode
|
||||
#define CMD22_MCU_DATA_LEN 0x00 // 0x22 Command: Device status query
|
||||
#define CMD23_MCU_DATA_LEN 0x05 // 0x23 Command: Set audio mode
|
||||
#define CMD24_MCU_DATA_LEN 0x00 // 0x24 Command: Send playback volume
|
||||
#define CMD25_MCU_DATA_LEN 0x00 // 0x25 Command: Send recording volume
|
||||
#define CMD27_MCU_DATA_LEN 0x00 // 0x27 Command: Special unmute (no data field)
|
||||
#define CMD28_MCU_DATA_LEN 0x00 // 0x28 Command: Audio format delay setting (no data field)
|
||||
|
||||
#define CMD_HID_TRANSPARENT_MCU_DATA_LEN 0x39 // 0xEE Command: HID transparent/OTA upgrade (57 bytes)
|
||||
```
|
||||
|
||||
## Communication Protocol Command Definitions
|
||||
|
||||
### Command Word Enumeration
|
||||
```c
|
||||
typedef enum
|
||||
{
|
||||
/****** Basic Control Commands (0x00-0x05) ******/
|
||||
CMD_STARTUP = 0x00, // System startup
|
||||
CMD_GET_PRODUCT_INFO = 0x01, // Product information query
|
||||
CMD_GET_BOOT_CFG = 0x02, // Power-on configuration read
|
||||
CMD_GET_AUD_MODE = 0x03, // Audio mode get
|
||||
CMD_GET_USER_CFG = 0x04, // User configuration get
|
||||
CMD_STARTUP_COMPLETE = 0x05, // Boot complete notification
|
||||
|
||||
CMD_GET_VERSION = 0xF1, // Version query
|
||||
|
||||
/****** Business Control Commands (0x20-0x2F) ******/
|
||||
CMD_REPORT_STATUS = 0x20, // Status report
|
||||
CMD_MEDIA_CONTROL = 0x21, // Media control
|
||||
CMD_SET_PLAY_FORMAT = 0x22, // Audio format setting
|
||||
CMD_SET_AUDIO_MODE = 0x23, // Audio mode setting
|
||||
CMD_SET_PLAY_VOL = 0x24, // Playback volume setting
|
||||
CMD_SET_REC_VOL = 0x25, // Recording volume setting
|
||||
CMD_SPECIAL_UNMUTE = 0x27, // Special unmute
|
||||
CMD_SET_AUDIO_FORMAT_DELAY = 0x28, // Audio format delay setting
|
||||
|
||||
CMD_HID_TRANSPARENT = 0xEE, // HID transparent/OTA upgrade command
|
||||
|
||||
CMD_COUNT = CMD_SET_REC_VOL + 1 // Total number of currently supported commands
|
||||
|
||||
} mcu_command_t;
|
||||
```
|
||||
|
||||
### Boot Option Enumeration (Bitmask Mode)
|
||||
|
||||
!!! note
|
||||
**Boot Option Enumeration (Bitmask Mode)**
|
||||
**Uses uint8_t to ensure single-byte storage, supports multiple option combinations**
|
||||
|
||||
```c
|
||||
typedef enum
|
||||
{
|
||||
BOOT_OPTION_USE_DEFAULTS = 0x00, // Use all default configurations
|
||||
BOOT_OPTION_UPDATE_BASIC_INFO = 0x01, // Update basic product information (bit0)
|
||||
BOOT_OPTION_UPDATE_POWER_CFG = 0x02, // Update power-on configuration information (bit1)
|
||||
BOOT_OPTION_UPDATE_OTHER_CFG = 0x04 // Reserved configuration, currently unused (bit2)
|
||||
} boot_option_t;
|
||||
```
|
||||
|
||||
### Media Control Enumeration
|
||||
```c
|
||||
typedef enum
|
||||
{
|
||||
MEDIA_KEY_VOLUME_UP = 0x00, // Volume increase
|
||||
MEDIA_KEY_VOLUME_DOWN = 0x01, // Volume decrease
|
||||
MEDIA_KEY_PLAY_PAUSE = 0x02, // Play/Pause
|
||||
MEDIA_KEY_NEXT_TRACK = 0x03, // Next track
|
||||
MEDIA_KEY_PREV_TRACK = 0x04, // Previous track
|
||||
MEDIA_KEY_FAST_FORWARD = 0x05, // Fast forward
|
||||
MEDIA_KEY_REWIND = 0x06, // Rewind
|
||||
MEDIA_KEY_MUTE = 0x07 // Mute toggle
|
||||
|
||||
// Reserved for expansion (0x08-0xFF reserved for protocol)
|
||||
|
||||
} media_control_t;
|
||||
```
|
||||
|
||||
## Audio Format Definitions
|
||||
|
||||
!!! note
|
||||
**Audio Stream Format Enumeration (Compatible with AES67-2020 Standard)**
|
||||
**Explicitly specifies underlying type as uint8_t to ensure 1-byte storage**
|
||||
|
||||
### Audio Stream Format Enumeration
|
||||
```c
|
||||
typedef enum
|
||||
{
|
||||
// PCM Sample Rate Formats (0x00-0x10)
|
||||
AUDIO_PCM_44100 = 0x00,
|
||||
AUDIO_PCM_48000 = 0x01,
|
||||
AUDIO_PCM_88200 = 0x02,
|
||||
AUDIO_PCM_96000 = 0x03,
|
||||
AUDIO_PCM_176400 = 0x04,
|
||||
AUDIO_PCM_192000 = 0x05,
|
||||
AUDIO_PCM_352800 = 0x06,
|
||||
AUDIO_PCM_384000 = 0x07,
|
||||
AUDIO_PCM_705600 = 0x08,
|
||||
AUDIO_PCM_768000 = 0x09,
|
||||
AUDIO_PCM_1441200 = 0x0A,
|
||||
AUDIO_PCM_1536000 = 0x0B,
|
||||
AUDIO_PCM_32000 = 0x0C,
|
||||
AUDIO_PCM_64000 = 0x0D,
|
||||
AUDIO_PCM_128000 = 0x0E,
|
||||
AUDIO_PCM_256000 = 0x0F,
|
||||
AUDIO_PCM_512000 = 0x10,
|
||||
|
||||
// DSD Formats (0x11-0x15)
|
||||
AUDIO_DSD_64 = 0x11,
|
||||
AUDIO_DSD_128 = 0x12,
|
||||
AUDIO_DSD_256 = 0x13,
|
||||
AUDIO_DSD_512 = 0x14,
|
||||
AUDIO_DSD_1024 = 0x15,
|
||||
|
||||
// MQA Formats (0x16-0x2D)
|
||||
AUDIO_MQA_44100 = 0x16,
|
||||
AUDIO_MQA_88200 = 0x17,
|
||||
AUDIO_MQA_176400 = 0x18,
|
||||
AUDIO_MQA_352800 = 0x19,
|
||||
AUDIO_MQA_705600 = 0x1A,
|
||||
AUDIO_MQA_1411200 = 0x1B,
|
||||
AUDIO_MQA_2822400 = 0x1C,
|
||||
AUDIO_MQA_5644800 = 0x1D,
|
||||
|
||||
// -- 48kHz Base Series --
|
||||
AUDIO_MQA_48000 = 0x1E,
|
||||
AUDIO_MQA_96000 = 0x1F,
|
||||
AUDIO_MQA_192000 = 0x20,
|
||||
AUDIO_MQA_384000 = 0x21,
|
||||
AUDIO_MQA_768000 = 0x22,
|
||||
AUDIO_MQA_1536000 = 0x23,
|
||||
AUDIO_MQA_3072000 = 0x24,
|
||||
AUDIO_MQA_6144000 = 0x25,
|
||||
|
||||
// -- Other Base Frequency Series --
|
||||
AUDIO_MQA_64000 = 0x26,
|
||||
AUDIO_MQA_128000 = 0x27,
|
||||
AUDIO_MQA_256000 = 0x28,
|
||||
AUDIO_MQA_512000 = 0x29,
|
||||
AUDIO_MQA_1024000 = 0x2A,
|
||||
AUDIO_MQA_2048000 = 0x2B,
|
||||
AUDIO_MQA_4096000 = 0x2C,
|
||||
AUDIO_MQA_8192000 = 0x2D,
|
||||
|
||||
// Special Reserved Value
|
||||
AUDIO_NO_USED = 0xFF
|
||||
|
||||
} audio_format_t;
|
||||
```
|
||||
|
||||
### Audio Type Enumeration
|
||||
!!! note
|
||||
**Audio Type Enumeration (Compatible with AES67-2020 Standard)**
|
||||
**Explicitly specifies underlying type as uint8_t to ensure 1-byte storage**
|
||||
|
||||
```c
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_TYPE_PCM = 0x00, // PCM standard audio
|
||||
AUDIO_TYPE_RESERVE = 0x01, // Protocol reserved field
|
||||
AUDIO_TYPE_MQA = 0x02, // MQA encoded audio
|
||||
AUDIO_TYPE_MQB = 0x03, // MQB encoded audio (secondary extension)
|
||||
AUDIO_TYPE_MQA_STUDIO = 0x04, // MQA Studio master quality
|
||||
AUDIO_TYPE_DSD = 0x05 // Direct Stream Digital
|
||||
|
||||
// 0x06-0xFF reserved for future expansion
|
||||
|
||||
} audio_type_t;
|
||||
```
|
||||
|
||||
## Command Data Structures
|
||||
|
||||
### Data Structure Definitions
|
||||
```c
|
||||
typedef uint8_t byte_pair[2];
|
||||
// Command data structure
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
uint8_t boot_option; // 0x00: Boot option data
|
||||
// Product basic information
|
||||
uint8_t vid_uac1[2]; // UAC1.0 vendor ID
|
||||
uint8_t pid_uac1[2]; // UAC1.0 product ID
|
||||
uint8_t vid_uac2[2]; // UAC2.0 vendor ID
|
||||
uint8_t pid_uac2[2]; // UAC2.0 product ID
|
||||
uint8_t product_manufacturer[16]; // Manufacturer name
|
||||
uint8_t product_name[16]; // Product name
|
||||
uint8_t product_serial[16]; // Serial number
|
||||
uint8_t basic_info_crc[4]; // Basic information CRC32
|
||||
// User configuration is power-on configuration information and also application runtime parameters
|
||||
uint8_t startup_status; // Startup status
|
||||
uint8_t audio_mode[5];
|
||||
uint8_t mute_duration[2]; // Mute duration (ms)
|
||||
uint8_t mic_volume; // Microphone volume, also recording volume
|
||||
uint8_t dac_l_volume; // Left channel volume (0-255)
|
||||
uint8_t dac_r_volume; // Right channel volume (0-255)
|
||||
uint8_t power_cfg_crc[4]; // Power-on configuration CRC32
|
||||
// Application runtime parameters
|
||||
uint8_t media_control; // Media control command
|
||||
uint8_t audio_format; // Audio format code
|
||||
uint8_t audio_type; // Audio type code
|
||||
} mcu_data_t;
|
||||
```
|
||||
|
||||
<!-- Structured Data Markup -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "TechArticle",
|
||||
"headline": "XU316 and MCU Communication Protocol Command Macro Definitions",
|
||||
"description": "This document provides command macro definitions related to the XU316 and MCU communication protocol, including frame format, command length, communication protocol, etc., to help developers implement XU316-MCU communication functionality.",
|
||||
"keywords": "XU316 communication protocol, MCU command macro definitions, audio format definitions, communication frame format, command data structures, audio type definitions",
|
||||
"author": {
|
||||
"@type": "Organization",
|
||||
"name": "Phaten Audio"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
title: XU316 and MCU Communication Protocol Command Macro Definitions
|
||||
description: This document provides command macro definitions for XU316 and MCU communication protocol, including frame format, command length, communication protocol, etc., to help developers implement communication functions between XU316 and MCU.
|
||||
keywords: XU316 communication protocol, MCU command macros, audio format definition, communication frame format, command data structure, audio type definition
|
||||
---
|
||||
|
||||
--8<-- "common/phaten_xmos_support_img.md"
|
||||
|
||||
# XU316 and MCU Communication Protocol Command Macro Definitions
|
||||
|
||||
## Document Description
|
||||
|
||||
This document provides command macro definitions related to the XU316 and MCU communication protocol, mainly including the following contents:
|
||||
|
||||
1. Communication frame format definition
|
||||
2. MCU command data length definition
|
||||
3. Communication protocol command enumeration
|
||||
4. Audio format and type definition
|
||||
5. Command data structure definition
|
||||
|
||||
These macro definitions and data structures are the foundation of XU316 and MCU communication. Developers need to correctly understand and use these definitions to implement communication functions.
|
||||
|
||||
## Communication Frame Format
|
||||
|
||||
### Basic Frame Format Definition
|
||||
@@ -1,407 +0,0 @@
|
||||
---
|
||||
title: XU316-MCU Communication Protocol Reference
|
||||
description: Detailed description of the communication protocol between XU316 and MCU, including data structures, command formats, and processing flows
|
||||
keywords: XU316, MCU, communication protocol, command reference
|
||||
hide:
|
||||
-toc
|
||||
---
|
||||
|
||||
--8<-- "common/phaten_xmos_support_img.md"
|
||||
|
||||
# XU316-MCU Communication Protocol Reference
|
||||
|
||||
## 1. Basic Data Structures
|
||||
|
||||
### 1.1 Ring Buffer
|
||||
```c
|
||||
#define RING_BUFFER_SIZE 256 // Ring buffer size for UART communication buffering
|
||||
|
||||
typedef struct {
|
||||
uint8_t buffer[RING_BUFFER_SIZE]; // Data storage area
|
||||
volatile uint16_t head; // Write position pointer
|
||||
volatile uint16_t tail; // Read position pointer
|
||||
volatile uint16_t count; // Current data count
|
||||
} ring_buffer_t;
|
||||
```
|
||||
|
||||
### 1.2 Audio Mode Definitions
|
||||
```c
|
||||
// Audio mode configuration array, each mode contains 5 bytes of configuration data
|
||||
static const uint8_t audio_modes[][5] = {
|
||||
{0x00, 0x80, 0xa9, 0x00, 0x01}, // USB-no-mqa mode
|
||||
{0x00, 0x80, 0x01, 0x00, 0x02}, // UAC1 mode
|
||||
{0x10, 0x80, 0x65, 0x10, 0x03}, // COAX mode
|
||||
{0x00, 0x80, 0x65, 0x10, 0x04}, // OPT mode
|
||||
{0x00, 0x80, 0xc5, 0x08, 0x05}, // SPDIF OUT mode
|
||||
{0x00, 0x82, 0xd5, 0x81, 0x06}, // I2S IN mode
|
||||
{0x20, 0x80, 0x65, 0x10, 0x07} // HDMI mode
|
||||
};
|
||||
|
||||
// Corresponding mode name array
|
||||
static const char *mode_names[] = {
|
||||
"USB-no-mqa",
|
||||
"UAC1",
|
||||
"COAX",
|
||||
"OPT",
|
||||
"SPDIF OUT",
|
||||
"I2S IN",
|
||||
"HDMI"
|
||||
};
|
||||
```
|
||||
|
||||
## 2. Initialization and Configuration
|
||||
|
||||
### 2.1 Device Initialization Information Print
|
||||
```c
|
||||
#define AUDIO_MODE_COUNT (sizeof(audio_modes) / sizeof(audio_modes[0]))
|
||||
|
||||
void print_init_info(void)
|
||||
{
|
||||
log_data(LOG_USER, "----------Device initialized----------\n");
|
||||
// Print UAC1.0 device information
|
||||
log_data(LOG_USER, "VID1: %02X%02X", mcu_data.vid_uac1[0], mcu_data.vid_uac1[1]);
|
||||
log_data(LOG_USER, "PID1: %02X%02X", mcu_data.pid_uac1[0], mcu_data.pid_uac1[1]);
|
||||
// Print UAC2.0 device information
|
||||
log_data(LOG_USER, "VID2: %02X%02X", mcu_data.vid_uac2[0], mcu_data.vid_uac2[1]);
|
||||
log_data(LOG_USER, "PID2: %02X%02X", mcu_data.pid_uac2[0], mcu_data.pid_uac2[1]);
|
||||
// Print product information
|
||||
log_data(LOG_USER, "Manufacturer: %s", mcu_data.product_manufacturer);
|
||||
log_data(LOG_USER, "Name: %s", mcu_data.product_name);
|
||||
log_data(LOG_USER, "Serial: %s", mcu_data.product_serial);
|
||||
// Print CRC checksum information
|
||||
log_data(LOG_USER, "Basic Info CRC: %02X%02X%02X%02X",
|
||||
mcu_data.basic_info_crc[0], mcu_data.basic_info_crc[1],
|
||||
mcu_data.basic_info_crc[2], mcu_data.basic_info_crc[3]);
|
||||
log_data(LOG_USER, "Power Config CRC: %02X%02X%02X%02X",
|
||||
mcu_data.power_cfg_crc[0], mcu_data.power_cfg_crc[1],
|
||||
mcu_data.power_cfg_crc[2], mcu_data.power_cfg_crc[3]);
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 Ring Buffer Initialization
|
||||
```c
|
||||
void ring_buffer_init(void) {
|
||||
uart_ring_buffer.head = 0; // Initialize write position
|
||||
uart_ring_buffer.tail = 0; // Initialize read position
|
||||
uart_ring_buffer.count = 0; // Initialize data count
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 Product Information Initialization
|
||||
```c
|
||||
void xu316_init(void)
|
||||
{
|
||||
// Default audio mode configuration (USB UAC2.0)
|
||||
uint8_t audio_mode[5] = {0x00, 0x80, 0xa9, 0x00, 0x01};
|
||||
|
||||
// Configure UAC1.0 device information
|
||||
mcu_data.vid_uac1[0] = 0x20;
|
||||
mcu_data.vid_uac1[1] = 0xB1; // VID = 0x20B1
|
||||
mcu_data.pid_uac1[0] = 0x00;
|
||||
mcu_data.pid_uac1[1] = 0x17; // PID = 0x0017
|
||||
|
||||
// Configure UAC2.0 device information
|
||||
mcu_data.vid_uac2[0] = 0x20;
|
||||
mcu_data.vid_uac2[1] = 0xB1; // VID = 0x20B1
|
||||
mcu_data.pid_uac2[0] = 0x00;
|
||||
mcu_data.pid_uac2[1] = 0x16; // PID = 0x0016
|
||||
|
||||
// Configure product information
|
||||
memcpy(mcu_data.product_manufacturer, "Phaten", 6);
|
||||
// Set product name
|
||||
memcpy(mcu_data.product_name, "XMOS XU316", 11);
|
||||
// Set product serial number
|
||||
memcpy(mcu_data.product_serial, "123456789ABCDEF", 15);
|
||||
|
||||
// Calculate and store basic information CRC32 checksum (56 bytes)
|
||||
crc = calculate_crc32(mcu_data.vid_uac1, 56);
|
||||
mcu_data.basic_info_crc[0] = (crc >> 24) & 0xFF;
|
||||
mcu_data.basic_info_crc[1] = (crc >> 16) & 0xFF;
|
||||
mcu_data.basic_info_crc[2] = (crc >> 8) & 0xFF;
|
||||
mcu_data.basic_info_crc[3] = crc & 0xFF;
|
||||
|
||||
// Initialize device status and audio configuration
|
||||
mcu_data.startup_status = 0x00;
|
||||
memcpy(&mcu_data.audio_mode, audio_mode, 5);
|
||||
|
||||
// Configure mute duration (400ms)
|
||||
mcu_data.mute_duration[0] = MUTE_DURATION_CONFIG >> 8;
|
||||
mcu_data.mute_duration[1] = MUTE_DURATION_CONFIG;
|
||||
|
||||
// Initialize volume settings
|
||||
mcu_data.mic_volume = MIC_VOLUME_CONFIG;
|
||||
// Initialize left and right channel DAC volume
|
||||
mcu_data.dac_l_volume = DAC_L_VOLUME_CONFIG;
|
||||
mcu_data.dac_r_volume = DAC_R_VOLUME_CONFIG;
|
||||
|
||||
// Calculate and store power configuration CRC32 checksum (10 bytes)
|
||||
crc = calculate_crc32((uint8_t *)&mcu_data.audio_mode, 0x0a);
|
||||
mcu_data.power_cfg_crc[0] = (crc >> 24) & 0xFF;
|
||||
mcu_data.power_cfg_crc[1] = (crc >> 16) & 0xFF;
|
||||
mcu_data.power_cfg_crc[2] = (crc >> 8) & 0xFF;
|
||||
mcu_data.power_cfg_crc[3] = crc & 0xFF;
|
||||
|
||||
// Initialize communication buffer
|
||||
ring_buffer_init();
|
||||
}
|
||||
```
|
||||
|
||||
## 3. Communication Buffer Operations
|
||||
|
||||
### 3.1 Ring Buffer Operation Functions
|
||||
```c
|
||||
// Write data to ring buffer
|
||||
uint8_t ring_buffer_write(uint8_t *data, uint16_t len) {
|
||||
uint16_t i;
|
||||
for(i = 0; i < len; i++) {
|
||||
if(uart_ring_buffer.count >= RING_BUFFER_SIZE) {
|
||||
return 0; // Buffer full, write failed
|
||||
}
|
||||
uart_ring_buffer.buffer[uart_ring_buffer.head] = data[i];
|
||||
uart_ring_buffer.head = (uart_ring_buffer.head + 1) % RING_BUFFER_SIZE;
|
||||
uart_ring_buffer.count++;
|
||||
}
|
||||
return 1; // Write successful
|
||||
}
|
||||
|
||||
// Read data from ring buffer
|
||||
uint8_t ring_buffer_read(uint8_t *data, uint16_t len) {
|
||||
uint16_t i;
|
||||
if(uart_ring_buffer.count < len) {
|
||||
return 0; // Insufficient data
|
||||
}
|
||||
for(i = 0; i < len; i++) {
|
||||
data[i] = uart_ring_buffer.buffer[uart_ring_buffer.tail];
|
||||
uart_ring_buffer.tail = (uart_ring_buffer.tail + 1) % RING_BUFFER_SIZE;
|
||||
uart_ring_buffer.count--;
|
||||
}
|
||||
return 1; // Read successful
|
||||
}
|
||||
|
||||
// Peek data (does not move read pointer)
|
||||
uint8_t ring_buffer_peek(uint8_t *data, uint16_t len) {
|
||||
uint16_t i;
|
||||
uint16_t temp_tail = uart_ring_buffer.tail;
|
||||
for(i = 0; i < len; i++) {
|
||||
data[i] = uart_ring_buffer.buffer[temp_tail];
|
||||
temp_tail = (temp_tail + 1) % RING_BUFFER_SIZE;
|
||||
}
|
||||
return 0; // Peek successful
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Checksum Calculation
|
||||
|
||||
### 4.1 CRC32 Calculation
|
||||
```c
|
||||
uint32_t calculate_crc32(const uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
const uint32_t poly = 0xEDB88320; // CRC32 polynomial
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
crc ^= buffer[i];
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (crc & 1) {
|
||||
crc = (crc >> 1) ^ poly;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ~crc; // Return CRC32 checksum value
|
||||
}
|
||||
|
||||
// Calculate simple checksum
|
||||
uint8_t xu316_calc_checksum(uint8_t *data, uint8_t len)
|
||||
{
|
||||
uint8_t sum = 0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
sum += data[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
```
|
||||
|
||||
## 5. Communication Protocol Processing
|
||||
|
||||
### 5.1 Frame Validation
|
||||
```c
|
||||
// Validate frame data integrity
|
||||
uint8_t uart_frame_check(uint8_t *buf, uint8_t len)
|
||||
{
|
||||
// Check minimum length requirement
|
||||
if (len < 6) { // Frame header(2) + version(1) + command(1) + length(2) + checksum(1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Verify frame header
|
||||
if (buf[0] != FRAME_HEADER_H || buf[1] != FRAME_HEADER_L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get data length (big-endian)
|
||||
uint16_t data_len = buf[4];
|
||||
|
||||
// Verify data length validity
|
||||
if (data_len > 256 || len < (data_len + 6)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Calculate and verify checksum
|
||||
uint8_t sum = xu316_calc_checksum(buf, data_len + 5);
|
||||
if (sum != buf[data_len + 5]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_TEMP(LOG_RECV, "", buf, len);
|
||||
return 1;
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 Data Frame Encapsulation
|
||||
```c
|
||||
int xu316_pack_frame(uint8_t cmd, uint8_t *data, uint8_t len)
|
||||
{
|
||||
uint8_t tx_data[256] = {0};
|
||||
if (len >= 255) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Build frame header
|
||||
tx_data[0] = FRAME_HEADER_H;
|
||||
tx_data[1] = FRAME_HEADER_L;
|
||||
tx_data[2] = PROTOCOL_VERSION_RX;
|
||||
tx_data[3] = cmd;
|
||||
tx_data[4] = len;
|
||||
|
||||
// Copy data payload
|
||||
if (data && len > 0) {
|
||||
memcpy(tx_data + 5, data, len);
|
||||
}
|
||||
|
||||
// Calculate and add checksum
|
||||
tx_data[len + 5] = xu316_calc_checksum(tx_data, len + 5);
|
||||
len += 6;
|
||||
|
||||
// Send data
|
||||
usart_dma_send(tx_data, len);
|
||||
LOG_INFO("Sending frame: cmd=0x%02X, len=%d", cmd, len);
|
||||
LOG_TEMP(LOG_SEND, "", tx_data, len);
|
||||
return len;
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 Frame Length Check
|
||||
```c
|
||||
int check_frame_length(uint8_t *buf, uint16_t len) {
|
||||
// Verify frame header
|
||||
if (buf[0] != FRAME_HEADER_H || buf[1] != FRAME_HEADER_L) {
|
||||
LOG_DEBUG("Frame header check failed %02x %02x", buf[0], buf[1]);
|
||||
return -1;
|
||||
}
|
||||
// Get data length (big-endian)
|
||||
int data_len = buf[4];
|
||||
// Return complete frame length
|
||||
return data_len + 6;
|
||||
}
|
||||
```
|
||||
|
||||
### 5.4 Data Reception Processing
|
||||
```c
|
||||
void uart_data_process(void)
|
||||
{
|
||||
uint8_t peek_buffer[8]; // Peek buffer
|
||||
uint8_t process_buffer[256]; // Process buffer
|
||||
int frame_length;
|
||||
|
||||
while(uart_ring_buffer.count >= 6) { // At least 6 bytes needed to start checking
|
||||
// Peek frame header information
|
||||
ring_buffer_peek(peek_buffer, 6);
|
||||
|
||||
// Debug output
|
||||
for(int i = 0; i < 6; i++) {
|
||||
LOG_DEBUG("peek_buffer[%d]: %02x", i, peek_buffer[i]);
|
||||
}
|
||||
|
||||
// Check frame length
|
||||
frame_length = check_frame_length(peek_buffer, 6);
|
||||
if(frame_length < 0) {
|
||||
// Invalid frame, discard one byte
|
||||
uint8_t dummy;
|
||||
ring_buffer_read(&dummy, 1);
|
||||
LOG_ERROR("Frame length check failed %02x", dummy);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if there is enough data
|
||||
if(uart_ring_buffer.count < frame_length) {
|
||||
LOG_ERROR("Not enough data");
|
||||
break; // Wait for more data
|
||||
}
|
||||
|
||||
// Read and process complete frame
|
||||
if(ring_buffer_read(process_buffer, frame_length)) {
|
||||
uart_data_parse();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.5 Data Parsing Processing
|
||||
```c
|
||||
int uart_data_parse(void)
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t cmd = 0;
|
||||
uint16_t data_len = 0;
|
||||
uint16_t rx_len = 0;
|
||||
uint8_t tmp;
|
||||
static uint8_t buffer[256] = {0};
|
||||
rx_len = g_rx_count;
|
||||
|
||||
// Verify frame integrity
|
||||
ret = uart_frame_check((uint8_t *)g_rx_data, rx_len);
|
||||
if (ret == 0) {
|
||||
LOG_ERROR("Frame check failed %d", rx_len);
|
||||
LOG_TEMP(LOG_RECV, "", g_rx_data, rx_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Parse frame information
|
||||
data_len = rx_len - 6;
|
||||
cmd = g_rx_data[3];
|
||||
if (g_rx_data[4] != data_len) {
|
||||
LOG_ERROR("Data length mismatch: expected %d, got %d", g_rx_data[4], data_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_DEBUG("Received frame: cmd=0x%02X, len=%d", cmd, data_len);
|
||||
LOG_VERBOSE("--------------------------------");
|
||||
LOG_VERBOSE("cmd : %02X", cmd);
|
||||
memcpy(buffer, g_rx_data + 5, data_len);
|
||||
|
||||
// Process data based on command type
|
||||
switch (cmd) {
|
||||
case 0x00: // Startup information
|
||||
// ... Process startup information ...
|
||||
break;
|
||||
|
||||
case 0x01: // Basic information
|
||||
// ... Process basic information ...
|
||||
break;
|
||||
|
||||
case 0x02: // Power configuration
|
||||
// ... Process power configuration ...
|
||||
break;
|
||||
|
||||
// ... Other command processing ...
|
||||
|
||||
default:
|
||||
LOG_ERROR("Unknown command: 0x%02X", cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,492 @@
|
||||
---
|
||||
title: XU316 MCU Development Example
|
||||
description: Detailed explanation of the communication protocol between XU316 and MCU, including data structures, command formats, and processing flow
|
||||
keywords: XU316, MCU, communication protocol, command reference
|
||||
---
|
||||
|
||||
# XU316 MCU Development Example
|
||||
|
||||
--8<-- "common/phaten_xmos_support_img.md"
|
||||
|
||||
This example is based on the GD32 platform. For other platforms, please adapt accordingly.
|
||||
|
||||
## Minimal Usage Example
|
||||
|
||||
This code demonstrates how to initialize the protocol layer and process data in the main loop. Users need to implement their own UART send function and call `ring_buffer_write` in the UART receive interrupt to write data into the ring buffer.
|
||||
|
||||
```c
|
||||
#include "xu316_protocol.h"
|
||||
|
||||
// Send callback: transmit data to XU316 via UART
|
||||
// Users need to implement uart_send based on their hardware
|
||||
void my_send(const uint8_t *data, uint16_t len) {
|
||||
uart_send(data, len);
|
||||
}
|
||||
|
||||
// Log callback: output debug information (optional)
|
||||
void my_log(const char *tag, const char *msg) {
|
||||
printf("[%s] %s\n", tag, msg);
|
||||
}
|
||||
|
||||
// Initialization
|
||||
void init(void) {
|
||||
xu316_port_t port = {
|
||||
.send = my_send,
|
||||
.log = my_log
|
||||
};
|
||||
xu316_register_port(&port);
|
||||
xu316_init();
|
||||
}
|
||||
|
||||
// Called in UART receive interrupt, writes received data to ring buffer
|
||||
void uart_rx_isr(uint8_t *data, uint16_t len) {
|
||||
ring_buffer_write(data, len);
|
||||
}
|
||||
|
||||
// Called periodically in main loop to process received commands
|
||||
void main_loop(void) {
|
||||
uart_data_process();
|
||||
}
|
||||
```
|
||||
|
||||
## Protocol Layer Functions
|
||||
|
||||
### Checksum Calculation
|
||||
|
||||
Calculates the cumulative sum of all bytes from the frame header to the data area, then takes the result modulo 256. This checksum is used to verify data frame integrity.
|
||||
|
||||
```c
|
||||
uint8_t xu316_calc_checksum(uint8_t *data, uint8_t len) {
|
||||
uint8_t sum = 0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
sum += data[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
```
|
||||
|
||||
### Frame Packing
|
||||
|
||||
Encapsulates the command and data into a protocol-compliant frame and sends it through the registered `send` callback.
|
||||
|
||||
Frame format: `Header(0x55AA) + Version(0x03) + Command + Data Length + Data + Checksum`
|
||||
|
||||
```c
|
||||
int xu316_pack_frame(uint8_t cmd, uint8_t *data, uint8_t len) {
|
||||
memset(g_tx_buffer, 0, sizeof(g_tx_buffer));
|
||||
g_tx_buffer[0] = FRAME_HEADER_H; // 0x55
|
||||
g_tx_buffer[1] = FRAME_HEADER_L; // 0xAA
|
||||
g_tx_buffer[2] = PROTOCOL_VERSION_RX; // 0x03 (MCU version)
|
||||
g_tx_buffer[3] = cmd; // Command
|
||||
g_tx_buffer[4] = len; // Data length
|
||||
|
||||
if (data && len > 0) {
|
||||
memcpy(g_tx_buffer + 5, data, len);
|
||||
}
|
||||
|
||||
// Calculate checksum (header + version + command + length + data)
|
||||
g_tx_buffer[len + 5] = xu316_calc_checksum(g_tx_buffer, len + 5);
|
||||
|
||||
// Send via registered callback
|
||||
if (g_xu316_port.send) {
|
||||
g_xu316_port.send(g_tx_buffer, len + 6);
|
||||
}
|
||||
return len + 6;
|
||||
}
|
||||
```
|
||||
|
||||
### Frame Extraction
|
||||
|
||||
Pre-reads data from the ring buffer and checks if the frame header is valid. Returns the complete frame length if valid, or `-1` if bytes need to be discarded.
|
||||
|
||||
```c
|
||||
static int check_frame_length(uint8_t *buf, uint16_t len) {
|
||||
// Check if header is 0x55AA
|
||||
if (buf[0] != FRAME_HEADER_H || buf[1] != FRAME_HEADER_L) {
|
||||
return -1; // Invalid header
|
||||
}
|
||||
// Return complete frame length = data length + 6 (header2 + version1 + cmd1 + len1 + checksum1)
|
||||
return buf[4] + 6;
|
||||
}
|
||||
```
|
||||
|
||||
### Data Processing Main Function
|
||||
|
||||
Called periodically in the main loop. Extracts complete data frames from the ring buffer, verifies frame header validity, confirms sufficient data length, copies the complete frame to the receive buffer, and then calls `uart_data_parse` for command parsing. If the frame header is invalid, bytes are discarded one by one until a valid header is found.
|
||||
|
||||
```c
|
||||
void uart_data_process(void) {
|
||||
uint8_t peek_buffer[8]; // Peek buffer
|
||||
uint8_t process_buffer[256]; // Frame data buffer
|
||||
int frame_length;
|
||||
|
||||
// Need at least 6 bytes to start checking header
|
||||
while (uart_ring_buffer.count >= 6) {
|
||||
// Peek 6 bytes to check header
|
||||
ring_buffer_peek(peek_buffer, 6);
|
||||
|
||||
// Check frame length
|
||||
frame_length = check_frame_length(peek_buffer, 6);
|
||||
if (frame_length < 0) {
|
||||
// Invalid header, discard 1 byte and continue searching
|
||||
uint8_t dummy;
|
||||
ring_buffer_read(&dummy, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if ring buffer has enough data for complete frame
|
||||
if (uart_ring_buffer.count < (uint16_t)frame_length) {
|
||||
break; // Insufficient data, wait for more
|
||||
}
|
||||
|
||||
// Read complete frame to processing buffer
|
||||
if (ring_buffer_read(process_buffer, (uint16_t)frame_length)) {
|
||||
// Copy complete frame to global receive buffer
|
||||
memcpy(g_rx_buffer, process_buffer, frame_length);
|
||||
g_rx_count = frame_length;
|
||||
g_rx_data = g_rx_buffer;
|
||||
// Call parse function to process command
|
||||
uart_data_parse();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Command Parsing
|
||||
|
||||
### Parse Entry
|
||||
|
||||
The core function of protocol processing. Verifies the received data frame, extracts the command and data area, then dispatches to the corresponding handler based on the command.
|
||||
|
||||
```c
|
||||
int uart_data_parse(void) {
|
||||
int ret = 0;
|
||||
uint8_t cmd = 0;
|
||||
uint16_t data_len = 0;
|
||||
uint16_t rx_len = (uint16_t)g_rx_count;
|
||||
static uint8_t buffer[256] = {0};
|
||||
|
||||
// Frame verification: check frame format and checksum
|
||||
ret = uart_frame_check((uint8_t *)g_rx_data, (uint8_t)rx_len);
|
||||
if (ret == 0) {
|
||||
return -1; // Frame verification failed
|
||||
}
|
||||
|
||||
// Calculate data area length: total length - 6 (header2 + version1 + cmd1 + len1 + checksum1)
|
||||
data_len = rx_len - 6;
|
||||
// Extract command (4th byte, index 3)
|
||||
cmd = g_rx_data[3];
|
||||
// Copy data area to buffer (from 6th byte, index 5)
|
||||
memcpy(buffer, g_rx_data + 5, data_len);
|
||||
|
||||
// Dispatch based on command
|
||||
switch (cmd) {
|
||||
case 0x00: /* Boot command */ break;
|
||||
case 0x01: /* Read product info */ break;
|
||||
case 0x02: /* Read power-on config */ break;
|
||||
case 0x03: /* Get audio mode */ break;
|
||||
case 0x04: /* Get user config */ break;
|
||||
case 0x05: /* Startup complete */ break;
|
||||
case 0x20: /* Status report */ break;
|
||||
case 0x22: /* Audio format set */ break;
|
||||
case 0x24: /* Playback volume */ break;
|
||||
case 0x25: /* Recording volume */ break;
|
||||
case 0x27: /* Unmute response */ break;
|
||||
case 0x28: /* Audio format delay */ break;
|
||||
case 0xEE: /* HID passthrough */ break;
|
||||
default: /* Unknown command */ break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
```
|
||||
|
||||
### Command Reference
|
||||
|
||||
#### Boot Command (0x00)
|
||||
|
||||
XU316 sends this command first after power-on or reboot. XU316 sends 17 bytes of data including VID/PID and CRC values. MCU compares CRC to determine if configuration needs updating, then replies with 1 byte of boot options.
|
||||
|
||||
```c
|
||||
case 0x00: {
|
||||
// XU316 data format:
|
||||
// Reboot reason(1B) + VID1(2B) + PID1(2B) + VID2(2B) + PID2(2B) + CRC1(4B) + CRC2(4B) = 17 bytes
|
||||
// MCU reply: Boot option(1B)
|
||||
|
||||
// Parse XU316 data
|
||||
uint8_t reboot_reason = buffer[0]; // 0x00=power-on, 0x01=mode switch, 0xFF=other
|
||||
uint8_t *vid_uac1 = buffer + 1; // UAC1.0 VID
|
||||
uint8_t *pid_uac1 = buffer + 3; // UAC1.0 PID
|
||||
uint8_t *vid_uac2 = buffer + 5; // UAC2.0 VID
|
||||
uint8_t *pid_uac2 = buffer + 7; // UAC2.0 PID
|
||||
uint8_t *basic_crc = buffer + 9; // Basic info CRC
|
||||
uint8_t *power_crc = buffer + 13; // Power config CRC
|
||||
|
||||
// Check if config update is needed: compare XU316 CRC with local stored CRC
|
||||
mcu_data.boot_option = 0;
|
||||
if (memcmp(basic_crc, mcu_data.basic_info_crc, 4) != 0) {
|
||||
mcu_data.boot_option |= BOOT_OPTION_UPDATE_BASIC_INFO; // Need to update basic info
|
||||
}
|
||||
if (memcmp(power_crc, mcu_data.power_cfg_crc, 4) != 0) {
|
||||
mcu_data.boot_option |= BOOT_OPTION_UPDATE_POWER_CFG; // Need to update power config
|
||||
}
|
||||
|
||||
// Send reply: boot option
|
||||
ret = xu316_pack_frame(cmd, &mcu_data.boot_option, CMD00_MCU_DATA_LEN);
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
#### Read Product Info (0x01)
|
||||
|
||||
XU316 requests product basic information. MCU replies with 60 bytes of data including VID, PID, manufacturer name, product name, serial number, and CRC.
|
||||
|
||||
```c
|
||||
case 0x01: {
|
||||
// XU316 sends: no data
|
||||
// MCU reply: 60 bytes product info
|
||||
// VID1(2B) + PID1(2B) + VID2(2B) + PID2(2B) +
|
||||
// Manufacturer(16B) + Product(16B) + Serial(16B) + CRC(4B)
|
||||
|
||||
// Recalculate CRC32 for basic info (first 56 bytes)
|
||||
crc = calculate_crc32(mcu_data.vid_uac1, 56);
|
||||
// Store CRC in big-endian
|
||||
mcu_data.basic_info_crc[0] = (uint8_t)((crc >> 24) & 0xFF);
|
||||
mcu_data.basic_info_crc[1] = (uint8_t)((crc >> 16) & 0xFF);
|
||||
mcu_data.basic_info_crc[2] = (uint8_t)((crc >> 8) & 0xFF);
|
||||
mcu_data.basic_info_crc[3] = (uint8_t)(crc & 0xFF);
|
||||
|
||||
// Send product info (60 bytes starting from vid_uac1)
|
||||
ret = xu316_pack_frame(cmd, mcu_data.vid_uac1, CMD01_MCU_DATA_LEN);
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
#### Read Power-On Config (0x02)
|
||||
|
||||
XU316 requests power-on configuration parameters. MCU replies with 14 bytes including boot status, audio mode, mute time, volume settings, and CRC.
|
||||
|
||||
```c
|
||||
case 0x02: {
|
||||
// XU316 sends: no data
|
||||
// MCU reply: 14 bytes config info
|
||||
// Boot status(1B) + Audio mode(5B) + Mute time(2B) +
|
||||
// Mic volume(1B) + Left vol(1B) + Right vol(1B) + CRC(4B)
|
||||
|
||||
// Recalculate CRC32 for power config (10 bytes starting from audio_mode)
|
||||
crc = calculate_crc32((uint8_t *)&mcu_data.audio_mode, 0x0a);
|
||||
// Store in big-endian
|
||||
mcu_data.power_cfg_crc[0] = (uint8_t)((crc >> 24) & 0xFF);
|
||||
mcu_data.power_cfg_crc[1] = (uint8_t)((crc >> 16) & 0xFF);
|
||||
mcu_data.power_cfg_crc[2] = (uint8_t)((crc >> 8) & 0xFF);
|
||||
mcu_data.power_cfg_crc[3] = (uint8_t)(crc & 0xFF);
|
||||
|
||||
// Send power config (14 bytes starting from audio_mode)
|
||||
ret = xu316_pack_frame(cmd, (uint8_t *)&mcu_data.audio_mode, CMD02_MCU_DATA_LEN);
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
#### Get Audio Mode (0x03)
|
||||
|
||||
XU316 requests current input/output mode. MCU replies with 5 bytes of audio mode configuration.
|
||||
|
||||
```c
|
||||
case 0x03: {
|
||||
// XU316 sends: no data
|
||||
// MCU reply: 5 bytes audio mode
|
||||
|
||||
ret = xu316_pack_frame(cmd, (uint8_t *)&mcu_data.audio_mode, CMD03_MCU_DATA_LEN);
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
#### Get User Config (0x04)
|
||||
|
||||
XU316 requests user configuration parameters. MCU replies with 14 bytes, same format as 0x02 command. Sets the currently selected audio mode and recalculates CRC.
|
||||
|
||||
```c
|
||||
case 0x04: {
|
||||
// XU316 sends: no data
|
||||
// MCU reply: 14 bytes user config (same format as 0x02)
|
||||
|
||||
// Set currently selected audio mode
|
||||
memcpy((uint8_t *)&mcu_data.audio_mode, audio_modes[g_current_mode], 5);
|
||||
|
||||
// Calculate CRC
|
||||
crc = calculate_crc32((uint8_t *)&mcu_data.audio_mode, 10);
|
||||
mcu_data.power_cfg_crc[0] = (uint8_t)((crc >> 24) & 0xFF);
|
||||
mcu_data.power_cfg_crc[1] = (uint8_t)((crc >> 16) & 0xFF);
|
||||
mcu_data.power_cfg_crc[2] = (uint8_t)((crc >> 8) & 0xFF);
|
||||
mcu_data.power_cfg_crc[3] = (uint8_t)(crc & 0xFF);
|
||||
|
||||
ret = xu316_pack_frame(cmd, (uint8_t *)&mcu_data.audio_mode, CMD04_MCU_DATA_LEN);
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
#### Startup Complete (0x05)
|
||||
|
||||
XU316 notifies MCU that startup is complete and sends current status data. MCU only needs to reply with acknowledgment (no data).
|
||||
|
||||
```c
|
||||
case 0x05: {
|
||||
// XU316 sends: 21 bytes status data
|
||||
// MCU reply: no data
|
||||
|
||||
// Save XU316 status to mcu_data structure
|
||||
memcpy(&mcu_data.startup_status, buffer, 15);
|
||||
|
||||
// Reply acknowledgment
|
||||
ret = xu316_pack_frame(cmd, NULL, CMD05_MCU_DATA_LEN);
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
#### Status Report (0x20)
|
||||
|
||||
XU316 proactively reports status changes. MCU saves status data and replies with acknowledgment.
|
||||
|
||||
```c
|
||||
case 0x20: {
|
||||
// XU316 sends: 20 bytes status data
|
||||
// Audio mode(5B) + Mute time(2B) + Mic vol(1B) + Left vol(1B) + Right vol(1B) + CRC(4B)
|
||||
// MCU reply: no data
|
||||
|
||||
// Save status data
|
||||
memcpy(&mcu_data.audio_mode, buffer, 14);
|
||||
|
||||
// Reply acknowledgment
|
||||
ret = xu316_pack_frame(cmd, NULL, CMD20_MCU_DATA_LEN);
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
#### Audio Format Setting (0x22)
|
||||
|
||||
XU316 notifies current playback audio format and type. MCU saves this information and replies with acknowledgment.
|
||||
|
||||
```c
|
||||
case 0x22: {
|
||||
// XU316 sends: 2 bytes (audio format + audio type)
|
||||
// MCU reply: no data
|
||||
|
||||
// Save audio format and type
|
||||
memcpy(&mcu_data.audio_format, buffer, 2);
|
||||
|
||||
// Reply acknowledgment
|
||||
ret = xu316_pack_frame(cmd, NULL, CMD22_MCU_DATA_LEN);
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
#### Playback Volume (0x24)
|
||||
|
||||
XU316 sends current playback volume. MCU saves left/right channel volume values and replies with acknowledgment.
|
||||
|
||||
```c
|
||||
case 0x24: {
|
||||
// XU316 sends: 2 bytes (left volume + right volume)
|
||||
// MCU reply: no data
|
||||
|
||||
// Save volume values
|
||||
memcpy(&mcu_data.dac_l_volume, buffer, 2);
|
||||
|
||||
// Reply acknowledgment
|
||||
ret = xu316_pack_frame(cmd, NULL, CMD24_MCU_DATA_LEN);
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
#### HID Passthrough (0xEE)
|
||||
|
||||
HID data passthrough or OTA upgrade data. XU316 sends 57 bytes, MCU replies with 57 bytes (echo mode).
|
||||
|
||||
```c
|
||||
case 0xEE: {
|
||||
// XU316 sends: 57 bytes HID/OTA data
|
||||
// MCU reply: 57 bytes (echo mode)
|
||||
|
||||
// Check version and data length
|
||||
if (g_rx_data[2] == 0x00 && g_rx_data[4] == CMD_HID_TRANSPARENT_DATA_LEN) {
|
||||
// Simple echo reply: return received data as-is
|
||||
ret = xu316_pack_frame(0xEE, buffer, CMD_HID_TRANSPARENT_MCU_DATA_LEN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
## MCU-Initiated Commands
|
||||
|
||||
The following commands are sent proactively by MCU to XU316.
|
||||
|
||||
### Unmute Command
|
||||
|
||||
Command `0x27`, data is 2 bytes of `0x00`.
|
||||
|
||||
```c
|
||||
void send_unmute_cmd(void) {
|
||||
uint8_t data[2] = {0x00, 0x00};
|
||||
xu316_pack_frame(0x27, data, 2);
|
||||
}
|
||||
```
|
||||
|
||||
### Audio Format Delay Command
|
||||
|
||||
Command `0x28`, data is 2 bytes of `0x00`.
|
||||
|
||||
```c
|
||||
void send_audio_format_delay_cmd(void) {
|
||||
uint8_t data[2] = {0x00, 0x00};
|
||||
xu316_pack_frame(0x28, data, 2);
|
||||
}
|
||||
```
|
||||
|
||||
### Media Control Command
|
||||
|
||||
Command `0x21`, data is 1 byte media control code.
|
||||
|
||||
```c
|
||||
void send_media_control(media_control_t cmd) {
|
||||
uint8_t data = (uint8_t)cmd;
|
||||
xu316_pack_frame(0x21, &data, 1);
|
||||
}
|
||||
|
||||
// Usage examples
|
||||
send_media_control(MEDIA_KEY_PLAY_PAUSE); // Play/Pause
|
||||
send_media_control(MEDIA_KEY_VOLUME_UP); // Volume up
|
||||
send_media_control(MEDIA_KEY_VOLUME_DOWN); // Volume down
|
||||
```
|
||||
|
||||
### Set Audio Mode
|
||||
|
||||
Command `0x23`, data is 5 bytes of audio mode configuration.
|
||||
|
||||
```c
|
||||
void set_audio_mode(uint8_t mode_index) {
|
||||
// audio_modes is a predefined array of 8 modes
|
||||
xu316_pack_frame(0x23, (uint8_t *)audio_modes[mode_index], 5);
|
||||
}
|
||||
|
||||
// 8 predefined audio modes
|
||||
static const uint8_t audio_modes[][5] = {
|
||||
{0x00, 0x80, 0xa9, 0x00, 0x01}, // UAC2.0->I2S
|
||||
{0x00, 0x80, 0x01, 0x00, 0x02}, // UAC1.0-I2S
|
||||
{0x10, 0x80, 0x65, 0x10, 0x03}, // S/PDIF1 IN-I2S OUT (COAX)
|
||||
{0x00, 0x80, 0x65, 0x10, 0x04}, // S/PDIF2 IN-I2S OUT (OPT)
|
||||
{0x00, 0x80, 0xc5, 0x08, 0x05}, // UAC2.0-SPDIF OUT
|
||||
{0x00, 0x82, 0xd5, 0x81, 0x06}, // I2S IN-I2S OUT
|
||||
{0x20, 0x80, 0x65, 0x10, 0x07}, // S/PDIF3 IN-I2S OUT (HDMI)
|
||||
{0x30, 0x80, 0x65, 0x10, 0x08} // S/PDIF4 IN-I2S OUT
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Consultation and Feedback
|
||||
|
||||
<details>
|
||||
<summary>Click to expand consultation and feedback form</summary>
|
||||
|
||||
--8<-- "common/customer_form.md"
|
||||
|
||||
</details>
|
||||
@@ -1,136 +0,0 @@
|
||||
---
|
||||
title: XU316 Audio Interface Control Code Examples
|
||||
description: This document provides code examples for XU316 audio interface control, including serial communication protocols, audio interface configuration, etc., to help developers quickly implement communication functions between XU316 and MCU.
|
||||
keywords: XU316 development, audio interface control, MCU communication, I2S configuration, serial protocol, audio sample rate, DSD configuration
|
||||
---
|
||||
|
||||
--8<-- "common/phaten_xmos_support_img.md"
|
||||
|
||||
# XU316 Audio Interface Control Code Examples
|
||||
|
||||
## Document Description
|
||||
|
||||
This document provides code examples for XU316 audio interface control, mainly including the following content:
|
||||
|
||||
1. Serial communication protocol definition
|
||||
2. Audio interface configuration parameters
|
||||
3. Audio sample rate and channel configuration
|
||||
4. Volume control parameter settings
|
||||
|
||||
These code examples can help developers quickly implement communication functions between XU316 and MCU, as well as configure various audio interface parameters.
|
||||
|
||||
## Serial Communication Protocol
|
||||
|
||||
### Protocol Definition
|
||||
```c
|
||||
#define SWAP16(x) ((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00))
|
||||
#define SWAP32(x) ((((x) >> 24) & 0x000000FF) | (((x) >> 8) & 0x0000FF00) | (((x) << 8) & 0x00FF0000) | (((x) << 24) & 0xFF000000))
|
||||
/* Protocol parsing */
|
||||
#define UART_FRAME_HEAD 0xAA
|
||||
#define UART_FRAME_TAIL 0x55
|
||||
#define HEX_UPPERCASE 0
|
||||
#define HEX_LOWERCASE 1
|
||||
#define HEX_TABLE HEX_UPPERCASE
|
||||
// Data frame structure
|
||||
typedef struct
|
||||
{
|
||||
uint8_t head; // Frame header 0xAA
|
||||
uint8_t cmd; // Command byte
|
||||
uint8_t len; // Data length
|
||||
uint8_t data[32]; // Data field
|
||||
uint8_t check; // Checksum
|
||||
uint8_t tail; // Frame tail 0x55
|
||||
} uart_frame_t;
|
||||
```
|
||||
|
||||
### Serial Buffer Management
|
||||
```c
|
||||
/* Serial port */
|
||||
/* buffer sizes */
|
||||
#define RX_BUFFER_SIZE 256
|
||||
#define TX_BUFFER_SIZE 256
|
||||
#define TX_BUFFER_NUM 2 // Double buffering
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t buffer[TX_BUFFER_SIZE];
|
||||
uint16_t size;
|
||||
uint8_t busy;
|
||||
} TX_BUFFER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
TX_BUFFER tx_buf[TX_BUFFER_NUM];
|
||||
uint8_t curr_buf;
|
||||
uint8_t next_buf;
|
||||
uint8_t dma_sending;
|
||||
} UART_TX_MANAGER;
|
||||
typedef enum
|
||||
{
|
||||
LOG_SEND,
|
||||
LOG_RECV,
|
||||
LOG_USER,
|
||||
LOG_ERR
|
||||
} log_dir_t;
|
||||
```
|
||||
|
||||
## Audio Interface Configuration
|
||||
|
||||
### Interface Mode Configuration
|
||||
```c
|
||||
// I2S master/slave mode configuration
|
||||
#define I2S_MODE I2S_MODE_MASTER // I2S master mode, XU316 as I2S master device
|
||||
// Synchronization mode configuration
|
||||
#define SYNC_MODE SYNC // Synchronous mode for audio clock synchronization
|
||||
// MIDI interface configuration
|
||||
#define MIDI_MODE MIDI_MODE_ENABLE // MIDI function enabled
|
||||
// SPDIF input interface configuration
|
||||
#define SPDIF_IN_MODE SPDIF_IN_MODE_ENABLE // SPDIF input function enabled
|
||||
// SPDIF output interface configuration
|
||||
#define SPDIF_OUT_MODE SPDIF_OUT_MODE_ENABLE // SPDIF output function enabled
|
||||
// ADAT input interface configuration (ADAT is an 8-channel digital audio transmission format)
|
||||
#define ADAT_IN_MODE ADAT_IN_MODE_ENABLE // ADAT input function enabled
|
||||
// ADAT output interface configuration
|
||||
#define ADAT_OUT_MODE ADAT_OUT_MODE_ENABLE // ADAT output function enabled
|
||||
// DSD output interface configuration (DSD is Direct Stream Digital for high-resolution audio)
|
||||
#define DSD_OUT_MODE DSD_OUT_MODE_ENABLE // DSD output function enabled
|
||||
```
|
||||
|
||||
### Audio Parameter Configuration
|
||||
```c
|
||||
// Initialize audio sample rate
|
||||
#define AUDIO_SAMPLE_RATE (uint8_t)AUDIO_SAMPLE_RATE_44100
|
||||
#define MQA_MODE MQA_MODE_DISABLE
|
||||
#define AUDIO_CLASS AUDIO_CLASS_UAC1
|
||||
#define AUDIO_WIDTH AUDIO_WIDTH_24
|
||||
// Initialize audio channels
|
||||
#define AUDIO_INPUT_CHANNEL 9
|
||||
#define AUDIO_OUTPUT_CHANNEL 3
|
||||
// Initialize audio type
|
||||
#define AUDIO_MODE USB_MODE
|
||||
// Mute duration 2 0-65535 (ms)
|
||||
#define MUTE_DURATION 100
|
||||
// Microphone default volume
|
||||
#define MIC_VOLUME 10
|
||||
// DAC left channel default volume 1 See DAC volume field description
|
||||
#define DAC_L_VOLUME 30
|
||||
// DAC right channel default volume 1 See DAC volume field description
|
||||
#define DAC_R_VOLUME 20
|
||||
```
|
||||
|
||||
<!-- Structured data markup -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "TechArticle",
|
||||
"headline": "XU316 Audio Interface Control Code Examples",
|
||||
"description": "This document provides code examples for XU316 audio interface control, including serial communication protocols, audio interface configuration, etc., to help developers quickly implement communication functions between XU316 and MCU.",
|
||||
"keywords": "XU316 development, audio interface control, MCU communication, I2S configuration, serial protocol, audio sample rate, DSD configuration",
|
||||
"author": {
|
||||
"@type": "Organization",
|
||||
"name": "Phaten Audio"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
```
|
||||
@@ -1,67 +1,43 @@
|
||||
---
|
||||
title: A316 No-Development Firmware MCU Development Guide
|
||||
description: This document provides comprehensive guidance for XU316-to-MCU communication development, including development steps, reference documentation, and frequently asked questions to help developers quickly implement communication functionality between XU316 and MCU.
|
||||
keywords: XU316 development, MCU communication development, audio interface control, communication protocol, development guidance, FAQ
|
||||
title: A316 Zero-Code Firmware MCU Development Guide
|
||||
description: Entry-level guidance for XU316-MCU communication development, helping developers understand the protocol, implement communication, and run example code step by step.
|
||||
keywords: XU316 development, MCU communication development, communication protocol, development guide, code examples
|
||||
---
|
||||
|
||||
--8<-- "common/phaten_xmos_support_img.md"
|
||||
|
||||
# A316 No-Development Firmware MCU Development Guide
|
||||
# A316 Zero-Code Firmware MCU Development Guide
|
||||
|
||||
## Development Overview
|
||||
|
||||
This document provides comprehensive guidance for XU316-to-MCU communication development, helping developers implement communication functionality between XU316 and MCU in the correct sequence. The development process is divided into the following main steps, each with corresponding reference documentation and detailed instructions.
|
||||
This document helps developers implement serial communication between XU316 and MCU in the correct sequence. The development process is divided into the following steps, each with corresponding reference documentation.
|
||||
|
||||
## Development Steps
|
||||
|
||||
<div class="grid" markdown>
|
||||
|
||||
=== "Step 1: Understanding Basic Concepts and Protocol Structure"
|
||||
**Objective**: Understand the basic concepts and protocol structure of XU316-MCU communication
|
||||
=== "Step 1: Understand Protocol Structure"
|
||||
**Objective**: Understand the frame format and command definitions for XU316-MCU communication
|
||||
|
||||
**Reference Documentation**: [:material-file-document-outline: XU316 and MCU Communication Protocol Command Macro Definitions](Command_Macros.md)
|
||||
**Reference Documentation**: [:material-file-document-outline: XU316 MCU Communication Protocol](../../protocols/xu316_zerocode_protocol.md)
|
||||
|
||||
**Key Learning Points**:
|
||||
|
||||
- Master the basic structure of frame format (frame header, command, data length, checksum, frame tail)
|
||||
- Understand data length definitions for various commands
|
||||
- Master the frame format (header `0x55AA`, version, command, data length, checksum)
|
||||
- Understand data length definitions for each command
|
||||
- Familiarize with audio format enumerations and type definitions
|
||||
- Learn the composition of command data structures
|
||||
|
||||
=== "Step 2: Implementing Basic Communication Functions"
|
||||
**Objective**: Implement basic communication functions between XU316 and MCU
|
||||
=== "Step 2: Run Example Code"
|
||||
**Objective**: Run the complete protocol communication example based on GD32 platform
|
||||
|
||||
**Reference Documentation**: [:material-file-document-outline: XU316 and MCU Communication Protocol Reference](Command_Reference.md)
|
||||
**Reference Documentation**: [:material-file-document-outline: XU316 MCU Development Example](./Development_Guide.md)
|
||||
|
||||
**Development Tasks**:
|
||||
**Example Contents**:
|
||||
|
||||
- Implement ring buffer initialization and management
|
||||
- Implement data frame encapsulation and transmission
|
||||
- Implement data frame reception and parsing
|
||||
- Implement CRC32 and simple checksum calculation
|
||||
- Implement basic communication protocol processing flow
|
||||
|
||||
=== "Step 3: Configuring Audio Interfaces and Parameters"
|
||||
**Objective**: Configure XU316 audio interfaces and related parameters
|
||||
|
||||
**Reference Documentation**: [:material-file-document-outline: XU316 Audio Interface Control Code Examples](Product_Content.md)
|
||||
|
||||
**Development Tasks**:
|
||||
|
||||
- Configure I2S master/slave mode
|
||||
- Set audio sampling rate and bit depth
|
||||
- Configure audio channel count
|
||||
- Set volume control parameters
|
||||
- Configure various audio interfaces (SPDIF, ADAT, DSD, etc.)
|
||||
|
||||
<!-- === "Step 4: Integration and Testing"
|
||||
**Objective**: Integrate all modules and perform functional testing
|
||||
|
||||
**Development Tasks**:
|
||||
- Integrate all communication function modules
|
||||
- Implement complete command processing flow
|
||||
- Perform functional testing and debugging
|
||||
- Optimize performance and stability -->
|
||||
- Minimal usage example (initialization, interrupt reception, main loop processing)
|
||||
- Protocol layer functions (checksum calculation, frame packing, frame extraction, data processing)
|
||||
- Complete command parsing code (0x00 ~ 0xEE)
|
||||
- MCU-initiated commands (unmute, media control, audio mode setting, etc.)
|
||||
|
||||
</div>
|
||||
|
||||
@@ -74,125 +50,17 @@ This document provides comprehensive guidance for XU316-to-MCU communication dev
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<!-- ## Frequently Asked Questions
|
||||
|
||||
### Communication Issues
|
||||
|
||||
!!! question "Q1: XU316 cannot send/receive data when connected to PC via serial port"
|
||||
**Problem Description**: XU316 cannot send or receive data when connected to PC via serial port, and logic analyzer cannot capture any data
|
||||
|
||||
**Solutions**:
|
||||
1. Check MCU response speed and configure XU316 with priority
|
||||
2. Verify if MCU is supplying power to XU316
|
||||
3. Ensure initialization is completed before XU316 sends power-on command
|
||||
|
||||
**Reference Documentation**: [:material-file-document-outline: Firmware-Free Development Issues Guide](../../faq/technical_faq/a316_firmware_dev_faq.md)
|
||||
|
||||
!!! question "Q2: Device recognized normally on PC but not recognized by phone"
|
||||
**Problem Description**: Device can be recognized and play normally on PC, but cannot be recognized when connected to phone
|
||||
|
||||
**Solutions**:
|
||||
1. Check device power supply mode design
|
||||
2. Modify device power supply and discharge sections
|
||||
3. Ensure device can receive power correctly when connected to phone
|
||||
|
||||
**Reference Documentation**: [:material-file-document-outline: Firmware-Free Development Issues Guide](../../faq/technical_faq/a316_firmware_dev_faq.md)
|
||||
|
||||
!!! question "Q3: IIS in command ineffective when WiFi is in slave mode"
|
||||
**Problem Description**: Sending IIS in command has no effect when WiFi is set to slave mode
|
||||
|
||||
**Solutions**:
|
||||
1. Check if firmware supports WiFi slave mode to XMOS master mode conversion
|
||||
2. Mount WiFi module to Bluetooth module
|
||||
3. Implement mode switching through Bluetooth module
|
||||
|
||||
**Reference Documentation**: [:material-file-document-outline: Firmware-Free Development Issues Guide](../../faq/technical_faq/a316_firmware_dev_faq.md)
|
||||
|
||||
### Configuration Issues
|
||||
|
||||
!!! question "Q4: Incorrect audio parameter configuration"
|
||||
**Problem Description**: Audio playback has noise or no sound
|
||||
|
||||
**Solutions**:
|
||||
1. Check if audio sampling rate configuration is correct
|
||||
2. Verify audio channel count settings
|
||||
3. Confirm volume parameter range
|
||||
4. Check I2S mode configuration
|
||||
|
||||
**Reference Documentation**: [:material-file-document-outline: XU316 Audio Interface Control Code Examples](Product_Content.md)
|
||||
|
||||
!!! question "Q5: Communication protocol parsing error"
|
||||
**Problem Description**: Received data is not parsed correctly
|
||||
|
||||
**Solutions**:
|
||||
1. Check if frame format definition is correct
|
||||
2. Verify checksum calculation method
|
||||
3. Confirm data length definition
|
||||
4. Check command word enumeration definition
|
||||
|
||||
**Reference Documentation**: [:material-file-document-outline: XU316 and MCU Communication Protocol Command Macro Definitions](Command_Macros.md) -->
|
||||
|
||||
<!-- ### Performance Issues
|
||||
|
||||
#### Q6: Slow communication speed or packet loss
|
||||
**Problem Description**: Data transmission is slow or data loss occurs
|
||||
|
||||
**Solutions**:
|
||||
1. Optimize ring buffer size
|
||||
2. Check DMA configuration
|
||||
3. Optimize data processing flow
|
||||
4. Add error retransmission mechanism
|
||||
|
||||
**Reference Documentation**: [:material-file-document-outline: XU316 and MCU Communication Protocol Reference](Command_Reference.md)
|
||||
|
||||
#### Q7: System stability issues
|
||||
**Problem Description**: System encounters exceptions after running for a period of time
|
||||
|
||||
**Solutions**:
|
||||
1. Add watchdog mechanism
|
||||
2. Optimize memory management
|
||||
3. Add exception handling
|
||||
4. Perform stress testing
|
||||
|
||||
## Development Recommendations
|
||||
|
||||
### Development Environment Preparation
|
||||
1. Ensure development environment is configured correctly
|
||||
2. Prepare necessary debugging tools
|
||||
3. Familiarize with relevant documentation and APIs
|
||||
|
||||
### Development Process Recommendations
|
||||
1. Follow the step-by-step development sequence
|
||||
2. Perform thorough testing after each step is completed
|
||||
3. Record and resolve encountered issues promptly
|
||||
4. Maintain clean and maintainable code
|
||||
|
||||
### Debugging Tips
|
||||
1. Use log output for debugging
|
||||
2. Use logic analyzer to analyze communication waveforms
|
||||
3. Test module by module
|
||||
4. Build comprehensive test cases
|
||||
|
||||
## Technical Support
|
||||
|
||||
If you encounter problems during development, you can obtain technical support through the following methods:
|
||||
|
||||
- **Documentation Reference**: Consult relevant technical documentation
|
||||
- **FAQ**: Refer to frequently asked questions
|
||||
- **Technical Support**: Contact technical support team -->
|
||||
|
||||
<!-- Structured Data Markup -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "TechArticle",
|
||||
"headline": "XU316 and MCU Communication Development Guide",
|
||||
"description": "This document provides comprehensive guidance for XU316 and MCU communication development, including development steps, reference documentation, and frequently asked questions.",
|
||||
"keywords": "XU316 development, MCU communication development, audio interface control, communication protocol, development guide, FAQ",
|
||||
"headline": "XU316 MCU Communication Development Guide",
|
||||
"description": "This document provides guidance for XU316-MCU communication development, including development steps and reference documentation.",
|
||||
"keywords": "XU316 development, MCU communication development, communication protocol, development guide, code examples",
|
||||
"author": {
|
||||
"@type": "Organization",
|
||||
"name": "Phaten Audio"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
@@ -1,198 +0,0 @@
|
||||
---
|
||||
title: A316 Firmware-Free MCU Development Guide
|
||||
description: This document provides comprehensive guidance on XU316 and MCU communication development, including development steps, reference documentation, and FAQ, helping developers quickly implement communication functions between XU316 and MCU.
|
||||
keywords: XU316 development, MCU communication development, audio interface control, communication protocol, development guide, FAQ
|
||||
---
|
||||
|
||||
--8<-- "common/phaten_xmos_support_img.md"
|
||||
|
||||
# A316 Firmware-Free MCU Development Guide
|
||||
|
||||
## Development Overview
|
||||
|
||||
This document provides comprehensive guidance on XU316 and MCU communication development, helping developers implement communication functions between XU316 and MCU in the correct sequence. The development process is divided into the following main steps, each with corresponding reference documentation and detailed instructions.
|
||||
|
||||
## Development Steps
|
||||
|
||||
<div class="grid" markdown>
|
||||
|
||||
=== "Step 1: Understanding Basic Concepts and Protocol Structure"
|
||||
**Objective**: Understand the basic concepts and protocol structure of XU316 and MCU communication
|
||||
|
||||
**Reference Document**: [:material-file-document-outline: XU316 and MCU Communication Protocol Command Macro Definitions](命令的相关宏.md)
|
||||
|
||||
**Key Learning Points**:
|
||||
|
||||
- Master the basic structure of frame format (frame header, command, data length, checksum, frame tail)
|
||||
- Understand data length definitions for various commands
|
||||
- Familiarize with audio format enumerations and type definitions
|
||||
- Understand the composition of command data structures
|
||||
|
||||
=== "Step 2: Implementing Basic Communication Functions"
|
||||
**Objective**: Implement basic communication functions between XU316 and MCU
|
||||
|
||||
**Reference Document**: [:material-file-document-outline: XU316 and MCU Communication Protocol Reference](命令相关.md)
|
||||
|
||||
**Development Tasks**:
|
||||
|
||||
- Implement ring buffer initialization and management
|
||||
- Implement data frame encapsulation and transmission
|
||||
- Implement data frame reception and parsing
|
||||
- Implement CRC32 and simple checksum calculation
|
||||
- Implement basic communication protocol processing flow
|
||||
|
||||
=== "Step 3: Configuring Audio Interfaces and Parameters"
|
||||
**Objective**: Configure XU316 audio interfaces and related parameters
|
||||
|
||||
**Reference Document**: [:material-file-document-outline: XU316 Audio Interface Control Code Examples](产品内容相关.md)
|
||||
|
||||
**Development Tasks**:
|
||||
|
||||
- Configure I2S master/slave mode
|
||||
- Set audio sampling rate and bit depth
|
||||
- Configure audio channel count
|
||||
- Set volume control parameters
|
||||
- Configure various audio interfaces (SPDIF, ADAT, DSD, etc.)
|
||||
|
||||
<!-- === "Step 4: Integration and Testing"
|
||||
**Objective**: Integrate all modules and conduct functional testing
|
||||
|
||||
**Development Tasks**:
|
||||
- Integrate all communication function modules
|
||||
- Implement complete command processing flow
|
||||
- Conduct functional testing and debugging
|
||||
- Optimize performance and stability -->
|
||||
|
||||
</div>
|
||||
|
||||
## Inquiry and Feedback
|
||||
|
||||
<details>
|
||||
<summary>Click to expand inquiry and feedback form</summary>
|
||||
|
||||
--8<-- "common/customer_form.md"
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<!-- ## FAQ
|
||||
|
||||
### Communication Issues
|
||||
|
||||
!!! question "Q1: Unable to send/receive data when XU316 connects to PC via serial port"
|
||||
**Issue**: Unable to send/receive data when XU316 connects to PC via serial port, and logic analyzer cannot capture data
|
||||
|
||||
**Solution**:
|
||||
1. Check MCU response speed, prioritize XU316 configuration
|
||||
2. Check if MCU is supplying power to XU316
|
||||
3. Ensure initialization is completed before XU316 sends power-on command
|
||||
|
||||
**Reference Document**: [:material-file-document-outline: Firmware-Free Development Issues Guide](../../faq/technical_faq/a316_firmware_dev_faq.md)
|
||||
|
||||
!!! question "Q2: Device recognized normally on PC but not recognized by mobile phone"
|
||||
**Issue**: Device can be recognized and play normally on PC, but cannot be recognized when connected to mobile phone
|
||||
|
||||
**Solution**:
|
||||
1. Check device power supply mode design
|
||||
2. Modify device power supply and discharge sections
|
||||
3. Ensure device can correctly receive power when connected to mobile phone
|
||||
|
||||
**Reference Document**: [:material-file-document-outline: Firmware-Free Development Issues Guide](../../faq/technical_faq/a316_firmware_dev_faq.md)
|
||||
|
||||
!!! question "Q3: IIS in command ineffective when WiFi is in slave mode"
|
||||
**Issue**: No effect after sending IIS in command when WiFi is set to slave mode
|
||||
|
||||
**Solution**:
|
||||
1. Check if firmware supports conversion from WiFi slave mode to XMOS master mode
|
||||
2. Mount WiFi module to Bluetooth module
|
||||
3. Implement mode switching function through Bluetooth module
|
||||
|
||||
**Reference Document**: [:material-file-document-outline: Firmware-Free Development Issues Guide](../../faq/technical_faq/a316_firmware_dev_faq.md)
|
||||
|
||||
### Configuration Issues
|
||||
|
||||
!!! question "Q4: Incorrect audio parameter configuration"
|
||||
**Issue**: Audio playback has noise or no sound
|
||||
|
||||
**Solution**:
|
||||
1. Check if audio sampling rate configuration is correct
|
||||
2. Verify audio channel count settings
|
||||
3. Confirm volume parameter range
|
||||
4. Check I2S mode configuration
|
||||
|
||||
**Reference Document**: [:material-file-document-outline: XU316 Audio Interface Control Code Examples](产品内容相关.md)
|
||||
|
||||
!!! question "Q5: Communication protocol parsing errors"
|
||||
**Issue**: Received data is parsed incorrectly
|
||||
|
||||
**Solution**:
|
||||
1. Check if frame format definition is correct
|
||||
2. Verify checksum calculation method
|
||||
3. Confirm data length definition
|
||||
4. Check command enumeration definition
|
||||
|
||||
**Reference Document**: [:material-file-document-outline: XU316 and MCU Communication Protocol Command Macro Definitions](命令的相关宏.md) -->
|
||||
|
||||
<!-- ### Performance Issues
|
||||
|
||||
#### Q6: Slow communication speed or packet loss
|
||||
**Issue**: Slow data transmission speed or data loss occurs
|
||||
|
||||
**Solution**:
|
||||
1. Optimize ring buffer size
|
||||
2. Check DMA configuration
|
||||
3. Optimize data processing flow
|
||||
4. Add error retransmission mechanism
|
||||
|
||||
**Reference Document**: [:material-file-document-outline: XU316 and MCU Communication Protocol Reference](命令相关.md)
|
||||
|
||||
#### Q7: System stability issues
|
||||
**Issue**: System experiences exceptions after running for a period of time
|
||||
|
||||
**Solution**:
|
||||
1. Add watchdog mechanism
|
||||
2. Optimize memory management
|
||||
3. Add exception handling
|
||||
4. Conduct stress testing
|
||||
|
||||
## Development Recommendations
|
||||
|
||||
### Development Environment Preparation
|
||||
1. Ensure development environment is configured correctly
|
||||
2. Prepare necessary debugging tools
|
||||
3. Familiarize with relevant documentation and APIs
|
||||
|
||||
### Development Process Recommendations
|
||||
1. Develop according to the step sequence
|
||||
2. Conduct thorough testing after completing each step
|
||||
3. Promptly record and resolve encountered issues
|
||||
4. Maintain clean and maintainable code
|
||||
|
||||
### Debugging Tips
|
||||
1. Use log output for debugging
|
||||
2. Use logic analyzer to analyze communication waveforms
|
||||
3. Test by module
|
||||
4. Establish complete test cases
|
||||
|
||||
## Technical Support
|
||||
|
||||
If you encounter issues during development, you can obtain technical support through the following methods:
|
||||
|
||||
- **Documentation Reference**: Review relevant technical documentation
|
||||
- **FAQ**: Refer to frequently asked questions
|
||||
- **Technical Support**: Contact technical support team -->
|
||||
|
||||
<!-- Structured data markup -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "TechArticle",
|
||||
"headline": "XU316 and MCU Communication Development Guide",
|
||||
"description": "This document provides comprehensive guidance on XU316 and MCU communication development, including development steps, reference documentation, and FAQ.",
|
||||
"keywords": "XU316 development, MCU communication development, audio interface control, communication protocol, development guide, FAQ",
|
||||
"author": {
|
||||
"@type": "Organization",
|
||||
"name": "Phaten Audio"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,138 +0,0 @@
|
||||
---
|
||||
title: XU316 Audio Interface Control Code Examples
|
||||
description: This document provides code examples for XU316 audio interface control, including serial communication protocols, audio interface configuration, etc., to help developers quickly implement communication between XU316 and MCU.
|
||||
keywords: XU316 development, audio interface control, MCU communication, I2S configuration, serial protocol, audio sample rate, DSD configuration
|
||||
---
|
||||
|
||||
--8<-- "common/phaten_xmos_support_img.md"
|
||||
|
||||
# XU316 Audio Interface Control Code Examples
|
||||
|
||||
## Document Overview
|
||||
|
||||
This document provides code examples for XU316 audio interface control, mainly covering the following content:
|
||||
|
||||
1. Serial communication protocol definitions
|
||||
2. Audio interface configuration parameters
|
||||
3. Audio sample rate and channel configuration
|
||||
4. Volume control parameter settings
|
||||
|
||||
These code examples help developers quickly implement communication between XU316 and MCU, as well as configure various audio interface parameters.
|
||||
|
||||
## Serial Communication Protocol
|
||||
|
||||
### Protocol Definitions
|
||||
```c
|
||||
#define SWAP16(x) ((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00))
|
||||
#define SWAP32(x) ((((x) >> 24) & 0x000000FF) | (((x) >> 8) & 0x0000FF00) | (((x) << 8) & 0x00FF0000) | (((x) << 24) & 0xFF000000))
|
||||
/* Protocol parsing */
|
||||
#define UART_FRAME_HEAD 0xAA
|
||||
#define UART_FRAME_TAIL 0x55
|
||||
#define HEX_UPPERCASE 0
|
||||
#define HEX_LOWERCASE 1
|
||||
#define HEX_TABLE HEX_UPPERCASE
|
||||
// Data frame structure
|
||||
typedef struct
|
||||
{
|
||||
uint8_t head; // Frame header 0xAA
|
||||
uint8_t cmd; // Command byte
|
||||
uint8_t len; // Data length
|
||||
uint8_t data[32]; // Data area
|
||||
uint8_t check; // Checksum
|
||||
uint8_t tail; // Frame tail 0x55
|
||||
} uart_frame_t;
|
||||
```
|
||||
|
||||
### Serial Buffer Management
|
||||
```c
|
||||
/* UART */
|
||||
/* buffer sizes */
|
||||
#define RX_BUFFER_SIZE 256
|
||||
#define TX_BUFFER_SIZE 256
|
||||
#define TX_BUFFER_NUM 2 // Double buffering
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t buffer[TX_BUFFER_SIZE];
|
||||
uint16_t size;
|
||||
uint8_t busy;
|
||||
} TX_BUFFER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
TX_BUFFER tx_buf[TX_BUFFER_NUM];
|
||||
uint8_t curr_buf;
|
||||
uint8_t next_buf;
|
||||
uint8_t dma_sending;
|
||||
} UART_TX_MANAGER;
|
||||
typedef enum
|
||||
{
|
||||
LOG_SEND,
|
||||
LOG_RECV,
|
||||
LOG_USER,
|
||||
LOG_ERR
|
||||
} log_dir_t;
|
||||
```
|
||||
|
||||
## Audio Interface Configuration
|
||||
|
||||
### Interface Mode Configuration
|
||||
```c
|
||||
// I2S master/slave mode configuration
|
||||
#define I2S_MODE I2S_MODE_MASTER // I2S master mode, XU316 acts as I2S master device
|
||||
// Synchronization mode configuration
|
||||
#define SYNC_MODE SYNC // Synchronization mode for audio clock synchronization
|
||||
// MIDI interface configuration
|
||||
#define MIDI_MODE MIDI_MODE_ENABLE // MIDI functionality enabled
|
||||
// SPDIF input interface configuration
|
||||
#define SPDIF_IN_MODE SPDIF_IN_MODE_ENABLE // SPDIF input functionality enabled
|
||||
// SPDIF output interface configuration
|
||||
#define SPDIF_OUT_MODE SPDIF_OUT_MODE_ENABLE // SPDIF output functionality enabled
|
||||
// ADAT input interface configuration (ADAT is an 8-channel digital audio transmission format)
|
||||
#define ADAT_IN_MODE ADAT_IN_MODE_ENABLE // ADAT input functionality enabled
|
||||
// ADAT output interface configuration
|
||||
#define ADAT_OUT_MODE ADAT_OUT_MODE_ENABLE // ADAT output functionality enabled
|
||||
// DSD output interface configuration (DSD is Direct Stream Digital for high-resolution audio)
|
||||
#define DSD_OUT_MODE DSD_OUT_MODE_ENABLE // DSD output functionality enabled
|
||||
```
|
||||
|
||||
### Audio Parameter Configuration
|
||||
```c
|
||||
// Initialize audio sample rate
|
||||
#define AUDIO_SAMPLE_RATE (uint8_t)AUDIO_SAMPLE_RATE_44100
|
||||
#define MQA_MODE MQA_MODE_DISABLE
|
||||
#define AUDIO_CLASS AUDIO_CLASS_UAC1
|
||||
#define AUDIO_WIDTH AUDIO_WIDTH_24
|
||||
// Initialize audio channels
|
||||
#define AUDIO_INPUT_CHANNEL 9
|
||||
#define AUDIO_OUTPUT_CHANNEL 3
|
||||
// Initialize audio type
|
||||
#define AUDIO_MODE USB_MODE
|
||||
// Mute duration 2 0-65535 (ms)
|
||||
#define MUTE_DURATION 100
|
||||
// Microphone default volume
|
||||
#define MIC_VOLUME 10
|
||||
// DAC left channel default volume 1 See DAC volume field description
|
||||
#define DAC_L_VOLUME 30
|
||||
// DAC right channel default volume 1 See DAC volume field description
|
||||
#define DAC_R_VOLUME 20
|
||||
```
|
||||
|
||||
<!-- Structured data markup -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "TechArticle",
|
||||
"headline": "XU316 Audio Interface Control Code Examples",
|
||||
"description": "This document provides code examples for XU316 audio interface control, including serial communication protocols, audio interface configuration, etc., to help developers quickly implement communication between XU316 and MCU.",
|
||||
"keywords": "XU316 development, audio interface control, MCU communication, I2S configuration, serial protocol, audio sample rate, DSD configuration",
|
||||
"author": {
|
||||
"@type": "Organization",
|
||||
"name": "Phaten Audio"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -1,286 +0,0 @@
|
||||
---
|
||||
title: XU316 and MCU Communication Protocol Command Macro Definitions
|
||||
description: This document provides command macro definitions for XU316 and MCU communication protocol, including frame format, command length, communication protocol, etc., to help developers implement communication functions between XU316 and MCU.
|
||||
keywords: XU316 communication protocol, MCU command macro definitions, audio format definitions, communication frame format, command data structure, audio type definitions
|
||||
---
|
||||
|
||||
--8<-- "common/phaten_xmos_support_img.md"
|
||||
|
||||
# XU316 and MCU Communication Protocol Command Macro Definitions
|
||||
|
||||
## Document Overview
|
||||
|
||||
This document provides command macro definitions related to the XU316 and MCU communication protocol, including the following content:
|
||||
|
||||
1. Communication frame format definitions
|
||||
2. MCU command data length definitions
|
||||
3. Communication protocol command enumerations
|
||||
4. Audio format and type definitions
|
||||
5. Command data structure definitions
|
||||
|
||||
These macro definitions and data structures form the foundation of XU316 and MCU communication. Developers need to correctly understand and use these definitions to implement communication functions.
|
||||
|
||||
## Communication Frame Format
|
||||
|
||||
### Basic Frame Format Definitions
|
||||
```c
|
||||
#define FRAME_HEADER_H 0x55
|
||||
#define FRAME_HEADER_L 0xAA
|
||||
#define PROTOCOL_VERSION 0x01
|
||||
#define PROTOCOL_VERSION_RX 0x03
|
||||
```
|
||||
|
||||
## Command Data Length Definitions
|
||||
|
||||
### XU316 Command Data Length
|
||||
```c
|
||||
#define CMD00_XU316_DATA_LEN 0x11 // 0x00 command: Start boot (startup options)
|
||||
#define CMD01_XU316_DATA_LEN 0x00 // 0x01 command: Read product information (60-byte firmware info)
|
||||
#define CMD02_XU316_DATA_LEN 0x00 // 0x02 command: Read power-on configuration (14-byte config parameters)
|
||||
#define CMD03_XU316_DATA_LEN 0x00 // 0x03 command: Get audio mode (5-byte mode parameters)
|
||||
#define CMD04_XU316_DATA_LEN 0x00 // 0x04 command: Get user configuration (14-byte user settings)
|
||||
#define CMD05_XU316_DATA_LEN 0x15 // 0x05 command: Startup complete (no data field)
|
||||
|
||||
#define CMDF1_XU316_DATA_LEN 0x03 // 0xF1 command: Version query (3-byte version info)
|
||||
|
||||
#define CMD20_XU316_DATA_LEN 0x14 // 0x20 command: Set volume
|
||||
#define CMD21_XU316_DATA_LEN 0x00 // 0x21 command: Audio effect mode
|
||||
#define CMD22_XU316_DATA_LEN 0x02 // 0x22 command: Device status query
|
||||
#define CMD23_XU316_DATA_LEN 0x00 // 0x23 command: Bluetooth control
|
||||
#define CMD24_XU316_DATA_LEN 0x02 // 0x24 command: Send playback volume
|
||||
#define CMD25_XU316_DATA_LEN 0x01 // 0x25 command: Send recording volume
|
||||
#define CMD27_XU316_DATA_LEN 0x00 // 0x27 command: Special unmute (no data field)
|
||||
#define CMD28_XU316_DATA_LEN 0x01 // 0x28 command: Audio format delay setting (1-byte parameter)
|
||||
|
||||
#define CMD_HID_TRANSPARENT_DATA_LEN 0x39 // 0xEE command: HID transparent transmission/OTA upgrade (57 bytes)
|
||||
```
|
||||
|
||||
### MCU Command Data Length
|
||||
```c
|
||||
#define CMD00_MCU_DATA_LEN 0x01 // 0x00 command: Start boot (startup options)
|
||||
#define CMD01_MCU_DATA_LEN 0x3C // 0x01 command: Read product information (60-byte firmware info)
|
||||
#define CMD02_MCU_DATA_LEN 0x0E // 0x02 command: Read power-on configuration (14-byte config parameters)
|
||||
#define CMD03_MCU_DATA_LEN 0x05 // 0x03 command: Get audio mode (5-byte mode parameters)
|
||||
#define CMD04_MCU_DATA_LEN 0x0E // 0x04 command: Get user configuration (14-byte user settings)
|
||||
#define CMD05_MCU_DATA_LEN 0x00 // 0x05 command: Startup complete (no data field)
|
||||
|
||||
#define CMDF1_MCU_DATA_LEN 0x00 // 0xF1 command: Version query (no data field)
|
||||
|
||||
#define CMD20_MCU_DATA_LEN 0x00 // 0x20 command: Set volume
|
||||
#define CMD21_MCU_DATA_LEN 0x01 // 0x21 command: Audio effect mode
|
||||
#define CMD22_MCU_DATA_LEN 0x00 // 0x22 command: Device status query
|
||||
#define CMD23_MCU_DATA_LEN 0x05 // 0x23 command: Set audio mode
|
||||
#define CMD24_MCU_DATA_LEN 0x00 // 0x24 command: Send playback volume
|
||||
#define CMD25_MCU_DATA_LEN 0x00 // 0x25 command: Send recording volume
|
||||
#define CMD27_MCU_DATA_LEN 0x00 // 0x27 command: Special unmute (no data field)
|
||||
#define CMD28_MCU_DATA_LEN 0x00 // 0x28 command: Audio format delay setting (no data field)
|
||||
|
||||
#define CMD_HID_TRANSPARENT_MCU_DATA_LEN 0x39 // 0xEE command: HID transparent transmission/OTA upgrade (57 bytes)
|
||||
```
|
||||
|
||||
## Communication Protocol Command Definitions
|
||||
|
||||
### Command Enumeration
|
||||
```c
|
||||
typedef enum
|
||||
{
|
||||
/****** Basic Control Commands (0x00-0x05) ******/
|
||||
CMD_STARTUP = 0x00, // System startup
|
||||
CMD_GET_PRODUCT_INFO = 0x01, // Product information query
|
||||
CMD_GET_BOOT_CFG = 0x02, // Power-on configuration read
|
||||
CMD_GET_AUD_MODE = 0x03, // Audio mode get
|
||||
CMD_GET_USER_CFG = 0x04, // User configuration get
|
||||
CMD_STARTUP_COMPLETE = 0x05, // Startup complete notification
|
||||
|
||||
CMD_GET_VERSION = 0xF1, // Version query
|
||||
|
||||
/****** Business Control Commands (0x20-0x2F) ******/
|
||||
CMD_REPORT_STATUS = 0x20, // Status report
|
||||
CMD_MEDIA_CONTROL = 0x21, // Media control
|
||||
CMD_SET_PLAY_FORMAT = 0x22, // Audio format setting
|
||||
CMD_SET_AUDIO_MODE = 0x23, // Audio mode setting
|
||||
CMD_SET_PLAY_VOL = 0x24, // Playback volume setting
|
||||
CMD_SET_REC_VOL = 0x25, // Recording volume setting
|
||||
CMD_SPECIAL_UNMUTE = 0x27, // Special unmute
|
||||
CMD_SET_AUDIO_FORMAT_DELAY = 0x28, // Audio format delay setting
|
||||
|
||||
CMD_HID_TRANSPARENT = 0xEE, // HID transparent transmission/OTA upgrade command
|
||||
|
||||
CMD_COUNT = CMD_SET_REC_VOL + 1 // Total number of currently supported commands
|
||||
|
||||
} mcu_command_t;
|
||||
```
|
||||
|
||||
### Boot Option Enumeration (Bitmask Mode)
|
||||
|
||||
!!! note
|
||||
**Boot Option Enumeration (Bitmask Mode)**
|
||||
**Uses uint8_t to ensure single-byte storage, supports multiple option combinations**
|
||||
|
||||
```c
|
||||
typedef enum
|
||||
{
|
||||
BOOT_OPTION_USE_DEFAULTS = 0x00, // Use all default configurations
|
||||
BOOT_OPTION_UPDATE_BASIC_INFO = 0x01, // Update basic product information (bit0)
|
||||
BOOT_OPTION_UPDATE_POWER_CFG = 0x02, // Update power-on configuration information (bit1)
|
||||
BOOT_OPTION_UPDATE_OTHER_CFG = 0x04 // Reserved configuration, currently unused (bit2)
|
||||
} boot_option_t;
|
||||
```
|
||||
|
||||
### Media Control Enumeration
|
||||
```c
|
||||
typedef enum
|
||||
{
|
||||
MEDIA_KEY_VOLUME_UP = 0x00, // Volume up
|
||||
MEDIA_KEY_VOLUME_DOWN = 0x01, // Volume down
|
||||
MEDIA_KEY_PLAY_PAUSE = 0x02, // Play/pause
|
||||
MEDIA_KEY_NEXT_TRACK = 0x03, // Next track
|
||||
MEDIA_KEY_PREV_TRACK = 0x04, // Previous track
|
||||
MEDIA_KEY_FAST_FORWARD = 0x05, // Fast forward
|
||||
MEDIA_KEY_REWIND = 0x06, // Rewind
|
||||
MEDIA_KEY_MUTE = 0x07 // Mute toggle
|
||||
|
||||
// Reserved extension space (0x08-0xFF reserved for protocol)
|
||||
|
||||
} media_control_t;
|
||||
```
|
||||
|
||||
## Audio Format Definitions
|
||||
|
||||
!!! note
|
||||
**Audio Stream Format Enumeration (AES67-2020 Standard Compatible)**
|
||||
**Explicitly specifies uint8_t as underlying type to ensure 1-byte storage**
|
||||
|
||||
### Audio Stream Format Enumeration
|
||||
```c
|
||||
typedef enum
|
||||
{
|
||||
// PCM sample rate formats (0x00-0x10)
|
||||
AUDIO_PCM_44100 = 0x00,
|
||||
AUDIO_PCM_48000 = 0x01,
|
||||
AUDIO_PCM_88200 = 0x02,
|
||||
AUDIO_PCM_96000 = 0x03,
|
||||
AUDIO_PCM_176400 = 0x04,
|
||||
AUDIO_PCM_192000 = 0x05,
|
||||
AUDIO_PCM_352800 = 0x06,
|
||||
AUDIO_PCM_384000 = 0x07,
|
||||
AUDIO_PCM_705600 = 0x08,
|
||||
AUDIO_PCM_768000 = 0x09,
|
||||
AUDIO_PCM_1441200 = 0x0A,
|
||||
AUDIO_PCM_1536000 = 0x0B,
|
||||
AUDIO_PCM_32000 = 0x0C,
|
||||
AUDIO_PCM_64000 = 0x0D,
|
||||
AUDIO_PCM_128000 = 0x0E,
|
||||
AUDIO_PCM_256000 = 0x0F,
|
||||
AUDIO_PCM_512000 = 0x10,
|
||||
|
||||
// DSD formats (0x11-0x15)
|
||||
AUDIO_DSD_64 = 0x11,
|
||||
AUDIO_DSD_128 = 0x12,
|
||||
AUDIO_DSD_256 = 0x13,
|
||||
AUDIO_DSD_512 = 0x14,
|
||||
AUDIO_DSD_1024 = 0x15,
|
||||
|
||||
// MQA formats (0x16-0x2D)
|
||||
AUDIO_MQA_44100 = 0x16,
|
||||
AUDIO_MQA_88200 = 0x17,
|
||||
AUDIO_MQA_176400 = 0x18,
|
||||
AUDIO_MQA_352800 = 0x19,
|
||||
AUDIO_MQA_705600 = 0x1A,
|
||||
AUDIO_MQA_1411200 = 0x1B,
|
||||
AUDIO_MQA_2822400 = 0x1C,
|
||||
AUDIO_MQA_5644800 = 0x1D,
|
||||
|
||||
// -- 48kHz series --
|
||||
AUDIO_MQA_48000 = 0x1E,
|
||||
AUDIO_MQA_96000 = 0x1F,
|
||||
AUDIO_MQA_192000 = 0x20,
|
||||
AUDIO_MQA_384000 = 0x21,
|
||||
AUDIO_MQA_768000 = 0x22,
|
||||
AUDIO_MQA_1536000 = 0x23,
|
||||
AUDIO_MQA_3072000 = 0x24,
|
||||
AUDIO_MQA_6144000 = 0x25,
|
||||
|
||||
// -- Other base frequency series --
|
||||
AUDIO_MQA_64000 = 0x26,
|
||||
AUDIO_MQA_128000 = 0x27,
|
||||
AUDIO_MQA_256000 = 0x28,
|
||||
AUDIO_MQA_512000 = 0x29,
|
||||
AUDIO_MQA_1024000 = 0x2A,
|
||||
AUDIO_MQA_2048000 = 0x2B,
|
||||
AUDIO_MQA_4096000 = 0x2C,
|
||||
AUDIO_MQA_8192000 = 0x2D,
|
||||
|
||||
// Special reserved value
|
||||
AUDIO_NO_USED = 0xFF
|
||||
|
||||
} audio_format_t;
|
||||
```
|
||||
|
||||
### Audio Type Enumeration
|
||||
!!! note
|
||||
**Audio Type Enumeration (AES67-2020 Standard Compatible)**
|
||||
**Explicitly specifies uint8_t as underlying type to ensure 1-byte storage**
|
||||
|
||||
```c
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_TYPE_PCM = 0x00, // PCM standard audio
|
||||
AUDIO_TYPE_RESERVE = 0x01, // Protocol reserved field
|
||||
AUDIO_TYPE_MQA = 0x02, // MQA encoded audio
|
||||
AUDIO_TYPE_MQB = 0x03, // MQB encoded audio (secondary extension)
|
||||
AUDIO_TYPE_MQA_STUDIO = 0x04, // MQA Studio master quality
|
||||
AUDIO_TYPE_DSD = 0x05 // Direct Stream Digital
|
||||
|
||||
// 0x06-0xFF reserved for future expansion
|
||||
|
||||
} audio_type_t;
|
||||
```
|
||||
|
||||
## Command Data Structure
|
||||
|
||||
### Data Structure Definition
|
||||
```c
|
||||
typedef uint8_t byte_pair[2];
|
||||
// Command data structure
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
uint8_t boot_option; // 0x00: Boot option data
|
||||
// Product basic information
|
||||
uint8_t vid_uac1[2]; // UAC1.0 vendor ID
|
||||
uint8_t pid_uac1[2]; // UAC1.0 product ID
|
||||
uint8_t vid_uac2[2]; // UAC2.0 vendor ID
|
||||
uint8_t pid_uac2[2]; // UAC2.0 product ID
|
||||
uint8_t product_manufacturer[16]; // Manufacturer name
|
||||
uint8_t product_name[16]; // Product name
|
||||
uint8_t product_serial[16]; // Serial number
|
||||
uint8_t basic_info_crc[4]; // Basic information CRC32
|
||||
// User configuration is power-on configuration and also application runtime parameters
|
||||
uint8_t startup_status; // Startup status
|
||||
uint8_t audio_mode[5];
|
||||
uint8_t mute_duration[2]; // Mute duration (ms)
|
||||
uint8_t mic_volume; // Microphone volume (recording volume)
|
||||
uint8_t dac_l_volume; // Left channel volume (0-255)
|
||||
uint8_t dac_r_volume; // Right channel volume (0-255)
|
||||
uint8_t power_cfg_crc[4]; // Power-on configuration CRC32
|
||||
// Application runtime parameters
|
||||
uint8_t media_control; // Media control command
|
||||
uint8_t audio_format; // Audio format code
|
||||
uint8_t audio_type; // Audio type code
|
||||
} mcu_data_t;
|
||||
```
|
||||
|
||||
<!-- Structured data markup -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "TechArticle",
|
||||
"headline": "XU316 and MCU Communication Protocol Command Macro Definitions",
|
||||
"description": "This document provides command macro definitions for XU316 and MCU communication protocol, including frame format, command length, communication protocol, etc., to help developers implement communication functions between XU316 and MCU.",
|
||||
"keywords": "XU316 communication protocol, MCU command macro definitions, audio format definitions, communication frame format, command data structure, audio type definitions",
|
||||
"author": {
|
||||
"@type": "Organization",
|
||||
"name": "Phaten Audio"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,407 +0,0 @@
|
||||
---
|
||||
title: XU316 and MCU Communication Protocol Reference
|
||||
description: Detailed description of the communication protocol between XU316 and MCU, including data structures, command formats, and processing flows
|
||||
keywords: XU316, MCU, communication protocol, command reference
|
||||
hide:
|
||||
-toc
|
||||
---
|
||||
|
||||
--8<-- "common/phaten_xmos_support_img.md"
|
||||
|
||||
# XU316 and MCU Communication Protocol Reference
|
||||
|
||||
## 1. Basic Data Structures
|
||||
|
||||
### 1.1 Ring Buffer
|
||||
```c
|
||||
#define RING_BUFFER_SIZE 256 // Ring buffer size for UART communication buffering
|
||||
|
||||
typedef struct {
|
||||
uint8_t buffer[RING_BUFFER_SIZE]; // Data storage area
|
||||
volatile uint16_t head; // Write position pointer
|
||||
volatile uint16_t tail; // Read position pointer
|
||||
volatile uint16_t count; // Current data count
|
||||
} ring_buffer_t;
|
||||
```
|
||||
|
||||
### 1.2 Audio Mode Definitions
|
||||
```c
|
||||
// Audio mode configuration array, each mode contains 5-byte configuration data
|
||||
static const uint8_t audio_modes[][5] = {
|
||||
{0x00, 0x80, 0xa9, 0x00, 0x01}, // USB-no-mqa mode
|
||||
{0x00, 0x80, 0x01, 0x00, 0x02}, // UAC1 mode
|
||||
{0x10, 0x80, 0x65, 0x10, 0x03}, // COAX mode
|
||||
{0x00, 0x80, 0x65, 0x10, 0x04}, // OPT mode
|
||||
{0x00, 0x80, 0xc5, 0x08, 0x05}, // SPDIF OUT mode
|
||||
{0x00, 0x82, 0xd5, 0x81, 0x06}, // I2S IN mode
|
||||
{0x20, 0x80, 0x65, 0x10, 0x07} // HDMI mode
|
||||
};
|
||||
|
||||
// Corresponding mode name array
|
||||
static const char *mode_names[] = {
|
||||
"USB-no-mqa",
|
||||
"UAC1",
|
||||
"COAX",
|
||||
"OPT",
|
||||
"SPDIF OUT",
|
||||
"I2S IN",
|
||||
"HDMI"
|
||||
};
|
||||
```
|
||||
|
||||
## 2. Initialization and Configuration
|
||||
|
||||
### 2.1 Device Initialization Information Print
|
||||
```c
|
||||
#define AUDIO_MODE_COUNT (sizeof(audio_modes) / sizeof(audio_modes[0]))
|
||||
|
||||
void print_init_info(void)
|
||||
{
|
||||
log_data(LOG_USER, "----------Device initialized----------\n");
|
||||
// Print UAC1.0 device information
|
||||
log_data(LOG_USER, "VID1: %02X%02X", mcu_data.vid_uac1[0], mcu_data.vid_uac1[1]);
|
||||
log_data(LOG_USER, "PID1: %02X%02X", mcu_data.pid_uac1[0], mcu_data.pid_uac1[1]);
|
||||
// Print UAC2.0 device information
|
||||
log_data(LOG_USER, "VID2: %02X%02X", mcu_data.vid_uac2[0], mcu_data.vid_uac2[1]);
|
||||
log_data(LOG_USER, "PID2: %02X%02X", mcu_data.pid_uac2[0], mcu_data.pid_uac2[1]);
|
||||
// Print product information
|
||||
log_data(LOG_USER, "Manufacturer: %s", mcu_data.product_manufacturer);
|
||||
log_data(LOG_USER, "Name: %s", mcu_data.product_name);
|
||||
log_data(LOG_USER, "Serial: %s", mcu_data.product_serial);
|
||||
// Print CRC checksum information
|
||||
log_data(LOG_USER, "Basic Info CRC: %02X%02X%02X%02X",
|
||||
mcu_data.basic_info_crc[0], mcu_data.basic_info_crc[1],
|
||||
mcu_data.basic_info_crc[2], mcu_data.basic_info_crc[3]);
|
||||
log_data(LOG_USER, "Power Config CRC: %02X%02X%02X%02X",
|
||||
mcu_data.power_cfg_crc[0], mcu_data.power_cfg_crc[1],
|
||||
mcu_data.power_cfg_crc[2], mcu_data.power_cfg_crc[3]);
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 Ring Buffer Initialization
|
||||
```c
|
||||
void ring_buffer_init(void) {
|
||||
uart_ring_buffer.head = 0; // Initialize write position
|
||||
uart_ring_buffer.tail = 0; // Initialize read position
|
||||
uart_ring_buffer.count = 0; // Initialize data count
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 Product Information Initialization
|
||||
```c
|
||||
void xu316_init(void)
|
||||
{
|
||||
// Default audio mode configuration (USB UAC2.0)
|
||||
uint8_t audio_mode[5] = {0x00, 0x80, 0xa9, 0x00, 0x01};
|
||||
|
||||
// Configure UAC1.0 device information
|
||||
mcu_data.vid_uac1[0] = 0x20;
|
||||
mcu_data.vid_uac1[1] = 0xB1; // VID = 0x20B1
|
||||
mcu_data.pid_uac1[0] = 0x00;
|
||||
mcu_data.pid_uac1[1] = 0x17; // PID = 0x0017
|
||||
|
||||
// Configure UAC2.0 device information
|
||||
mcu_data.vid_uac2[0] = 0x20;
|
||||
mcu_data.vid_uac2[1] = 0xB1; // VID = 0x20B1
|
||||
mcu_data.pid_uac2[0] = 0x00;
|
||||
mcu_data.pid_uac2[1] = 0x16; // PID = 0x0016
|
||||
|
||||
// Configure product information
|
||||
memcpy(mcu_data.product_manufacturer, "Phaten", 6);
|
||||
// Set product name
|
||||
memcpy(mcu_data.product_name, "XMOS XU316", 11);
|
||||
// Set product serial number
|
||||
memcpy(mcu_data.product_serial, "123456789ABCDEF", 15);
|
||||
|
||||
// Calculate and store basic information CRC32 checksum (56 bytes)
|
||||
crc = calculate_crc32(mcu_data.vid_uac1, 56);
|
||||
mcu_data.basic_info_crc[0] = (crc >> 24) & 0xFF;
|
||||
mcu_data.basic_info_crc[1] = (crc >> 16) & 0xFF;
|
||||
mcu_data.basic_info_crc[2] = (crc >> 8) & 0xFF;
|
||||
mcu_data.basic_info_crc[3] = crc & 0xFF;
|
||||
|
||||
// Initialize device status and audio configuration
|
||||
mcu_data.startup_status = 0x00;
|
||||
memcpy(&mcu_data.audio_mode, audio_mode, 5);
|
||||
|
||||
// Configure mute duration (400ms)
|
||||
mcu_data.mute_duration[0] = MUTE_DURATION_CONFIG >> 8;
|
||||
mcu_data.mute_duration[1] = MUTE_DURATION_CONFIG;
|
||||
|
||||
// Initialize volume settings
|
||||
mcu_data.mic_volume = MIC_VOLUME_CONFIG;
|
||||
// Initialize left and right channel DAC volume
|
||||
mcu_data.dac_l_volume = DAC_L_VOLUME_CONFIG;
|
||||
mcu_data.dac_r_volume = DAC_R_VOLUME_CONFIG;
|
||||
|
||||
// Calculate and store power configuration CRC32 checksum (10 bytes)
|
||||
crc = calculate_crc32((uint8_t *)&mcu_data.audio_mode, 0x0a);
|
||||
mcu_data.power_cfg_crc[0] = (crc >> 24) & 0xFF;
|
||||
mcu_data.power_cfg_crc[1] = (crc >> 16) & 0xFF;
|
||||
mcu_data.power_cfg_crc[2] = (crc >> 8) & 0xFF;
|
||||
mcu_data.power_cfg_crc[3] = crc & 0xFF;
|
||||
|
||||
// Initialize communication buffer
|
||||
ring_buffer_init();
|
||||
}
|
||||
```
|
||||
|
||||
## 3. Communication Buffer Operations
|
||||
|
||||
### 3.1 Ring Buffer Operation Functions
|
||||
```c
|
||||
// Write data to ring buffer
|
||||
uint8_t ring_buffer_write(uint8_t *data, uint16_t len) {
|
||||
uint16_t i;
|
||||
for(i = 0; i < len; i++) {
|
||||
if(uart_ring_buffer.count >= RING_BUFFER_SIZE) {
|
||||
return 0; // Buffer full, write failed
|
||||
}
|
||||
uart_ring_buffer.buffer[uart_ring_buffer.head] = data[i];
|
||||
uart_ring_buffer.head = (uart_ring_buffer.head + 1) % RING_BUFFER_SIZE;
|
||||
uart_ring_buffer.count++;
|
||||
}
|
||||
return 1; // Write successful
|
||||
}
|
||||
|
||||
// Read data from ring buffer
|
||||
uint8_t ring_buffer_read(uint8_t *data, uint16_t len) {
|
||||
uint16_t i;
|
||||
if(uart_ring_buffer.count < len) {
|
||||
return 0; // Insufficient data
|
||||
}
|
||||
for(i = 0; i < len; i++) {
|
||||
data[i] = uart_ring_buffer.buffer[uart_ring_buffer.tail];
|
||||
uart_ring_buffer.tail = (uart_ring_buffer.tail + 1) % RING_BUFFER_SIZE;
|
||||
uart_ring_buffer.count--;
|
||||
}
|
||||
return 1; // Read successful
|
||||
}
|
||||
|
||||
// Peek data (without moving read pointer)
|
||||
uint8_t ring_buffer_peek(uint8_t *data, uint16_t len) {
|
||||
uint16_t i;
|
||||
uint16_t temp_tail = uart_ring_buffer.tail;
|
||||
for(i = 0; i < len; i++) {
|
||||
data[i] = uart_ring_buffer.buffer[temp_tail];
|
||||
temp_tail = (temp_tail + 1) % RING_BUFFER_SIZE;
|
||||
}
|
||||
return 0; // Peek successful
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Checksum Calculation
|
||||
|
||||
### 4.1 CRC32 Calculation
|
||||
```c
|
||||
uint32_t calculate_crc32(const uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
const uint32_t poly = 0xEDB88320; // CRC32 polynomial
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
crc ^= buffer[i];
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (crc & 1) {
|
||||
crc = (crc >> 1) ^ poly;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ~crc; // Return CRC32 checksum value
|
||||
}
|
||||
|
||||
// Calculate simple checksum
|
||||
uint8_t xu316_calc_checksum(uint8_t *data, uint8_t len)
|
||||
{
|
||||
uint8_t sum = 0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
sum += data[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
```
|
||||
|
||||
## 5. Communication Protocol Processing
|
||||
|
||||
### 5.1 Frame Validation
|
||||
```c
|
||||
// Validate frame data integrity
|
||||
uint8_t uart_frame_check(uint8_t *buf, uint8_t len)
|
||||
{
|
||||
// Check minimum length requirement
|
||||
if (len < 6) { // Header(2) + Version(1) + Command(1) + Length(2) + Checksum(1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Verify frame header
|
||||
if (buf[0] != FRAME_HEADER_H || buf[1] != FRAME_HEADER_L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get data length (big-endian)
|
||||
uint16_t data_len = buf[4];
|
||||
|
||||
// Verify data length validity
|
||||
if (data_len > 256 || len < (data_len + 6)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Calculate and verify checksum
|
||||
uint8_t sum = xu316_calc_checksum(buf, data_len + 5);
|
||||
if (sum != buf[data_len + 5]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_TEMP(LOG_RECV, "", buf, len);
|
||||
return 1;
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 Data Frame Encapsulation
|
||||
```c
|
||||
int xu316_pack_frame(uint8_t cmd, uint8_t *data, uint8_t len)
|
||||
{
|
||||
uint8_t tx_data[256] = {0};
|
||||
if (len >= 255) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Construct frame header
|
||||
tx_data[0] = FRAME_HEADER_H;
|
||||
tx_data[1] = FRAME_HEADER_L;
|
||||
tx_data[2] = PROTOCOL_VERSION_RX;
|
||||
tx_data[3] = cmd;
|
||||
tx_data[4] = len;
|
||||
|
||||
// Copy data payload
|
||||
if (data && len > 0) {
|
||||
memcpy(tx_data + 5, data, len);
|
||||
}
|
||||
|
||||
// Calculate and append checksum
|
||||
tx_data[len + 5] = xu316_calc_checksum(tx_data, len + 5);
|
||||
len += 6;
|
||||
|
||||
// Send data
|
||||
usart_dma_send(tx_data, len);
|
||||
LOG_INFO("Sending frame: cmd=0x%02X, len=%d", cmd, len);
|
||||
LOG_TEMP(LOG_SEND, "", tx_data, len);
|
||||
return len;
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 Frame Length Check
|
||||
```c
|
||||
int check_frame_length(uint8_t *buf, uint16_t len) {
|
||||
// Verify frame header
|
||||
if (buf[0] != FRAME_HEADER_H || buf[1] != FRAME_HEADER_L) {
|
||||
LOG_DEBUG("Frame header check failed %02x %02x", buf[0], buf[1]);
|
||||
return -1;
|
||||
}
|
||||
// Get data length (big-endian)
|
||||
int data_len = buf[4];
|
||||
// Return complete frame length
|
||||
return data_len + 6;
|
||||
}
|
||||
```
|
||||
|
||||
### 5.4 Data Reception Processing
|
||||
```c
|
||||
void uart_data_process(void)
|
||||
{
|
||||
uint8_t peek_buffer[8]; // Peek buffer
|
||||
uint8_t process_buffer[256]; // Processing buffer
|
||||
int frame_length;
|
||||
|
||||
while(uart_ring_buffer.count >= 6) { // At least 6 bytes needed to start checking
|
||||
// Peek frame header information
|
||||
ring_buffer_peek(peek_buffer, 6);
|
||||
|
||||
// Debug output
|
||||
for(int i = 0; i < 6; i++) {
|
||||
LOG_DEBUG("peek_buffer[%d]: %02x", i, peek_buffer[i]);
|
||||
}
|
||||
|
||||
// Check frame length
|
||||
frame_length = check_frame_length(peek_buffer, 6);
|
||||
if(frame_length < 0) {
|
||||
// Invalid frame, discard one byte
|
||||
uint8_t dummy;
|
||||
ring_buffer_read(&dummy, 1);
|
||||
LOG_ERROR("Frame length check failed %02x", dummy);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if enough data is available
|
||||
if(uart_ring_buffer.count < frame_length) {
|
||||
LOG_ERROR("Not enough data");
|
||||
break; // Wait for more data
|
||||
}
|
||||
|
||||
// Read and process complete frame
|
||||
if(ring_buffer_read(process_buffer, frame_length)) {
|
||||
uart_data_parse();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.5 Data Parsing and Processing
|
||||
```c
|
||||
int uart_data_parse(void)
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t cmd = 0;
|
||||
uint16_t data_len = 0;
|
||||
uint16_t rx_len = 0;
|
||||
uint8_t tmp;
|
||||
static uint8_t buffer[256] = {0};
|
||||
rx_len = g_rx_count;
|
||||
|
||||
// Verify frame integrity
|
||||
ret = uart_frame_check((uint8_t *)g_rx_data, rx_len);
|
||||
if (ret == 0) {
|
||||
LOG_ERROR("Frame check failed %d", rx_len);
|
||||
LOG_TEMP(LOG_RECV, "", g_rx_data, rx_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Parse frame information
|
||||
data_len = rx_len - 6;
|
||||
cmd = g_rx_data[3];
|
||||
if (g_rx_data[4] != data_len) {
|
||||
LOG_ERROR("Data length mismatch: expected %d, got %d", g_rx_data[4], data_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_DEBUG("Received frame: cmd=0x%02X, len=%d", cmd, data_len);
|
||||
LOG_VERBOSE("--------------------------------");
|
||||
LOG_VERBOSE("cmd : %02X", cmd);
|
||||
memcpy(buffer, g_rx_data + 5, data_len);
|
||||
|
||||
// Process data based on command type
|
||||
switch (cmd) {
|
||||
case 0x00: // Startup information
|
||||
// ... Process startup information ...
|
||||
break;
|
||||
|
||||
case 0x01: // Basic information
|
||||
// ... Process basic information ...
|
||||
break;
|
||||
|
||||
case 0x02: // Power configuration
|
||||
// ... Process power configuration ...
|
||||
break;
|
||||
|
||||
// ... Other command processing ...
|
||||
|
||||
default:
|
||||
LOG_ERROR("Unknown command: 0x%02X", cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user