26 Commits

Author SHA1 Message Date
Steven Dan
418ea8fdd4 1.0.9 2026-04-09 14:30:23 +08:00
Steven Dan
35846cffd3 mic detection 2026-04-09 14:30:04 +08:00
Steven Dan
f1c0084325 flash attribure 2026-04-09 10:53:00 +08:00
Steven Dan
1b1259cdbf add mute2 2026-04-08 13:26:15 +08:00
Steven Dan
8262e59344 1.0.8 2026-04-08 09:52:34 +08:00
Steven Dan
c4b10f7b4e add flash supprt 2026-04-08 09:52:19 +08:00
Steven Dan
9073ed3b3a mute led act as blinking 2026-03-31 11:39:21 +08:00
Steven Dan
eae7e2178b update eq_flash_storage 2026-03-31 10:58:58 +08:00
Steven Dan
00e7cab17a update stackfunction 2026-03-31 10:58:35 +08:00
Steven Dan
38f033ace0 add SetEqDataChan for EQ_EN only 2026-03-31 10:19:43 +08:00
Steven Dan
cb4a7bad5b update f2 f3 to 16bit 2026-03-31 10:19:11 +08:00
Steven Dan
8246d6fbda 1.0.6 2026-03-30 20:14:15 +08:00
Steven Dan
19d9c64b62 add mute handler 2 2026-03-30 20:13:47 +08:00
Steven Dan
c3202488f6 remove stackfunction 2026-03-30 20:13:05 +08:00
Steven Dan
fe0028bba4 update fptrgroup 2026-03-30 20:07:01 +08:00
Steven Dan
898ef085c0 add mute handler 2026-03-30 20:01:40 +08:00
Steven Dan
f548845a29 key_program 2026-03-30 18:29:19 +08:00
Steven Dan
a4bd3cfc69 update sy102_hid_protocol.md 2026-03-30 16:24:47 +08:00
Steven Dan
c0335779de music 24bit only 2026-03-30 12:19:23 +08:00
Steven Dan
5dbe5d57f3 update uac1 reboot check 2026-03-30 12:18:55 +08:00
Steven Dan
ac774400b3 uac1 playback distortion 2026-03-30 11:32:44 +08:00
Steven Dan
f8ea57d683 uac1 hid 2026-03-30 10:28:50 +08:00
Steven Dan
12c1535e51 uac1 settings 2026-03-28 22:44:14 +08:00
Steven Dan
6c7d3419d7 mute before change mclk 2026-03-28 18:34:12 +08:00
Steven Dan
c821c007a3 uac1 use uac2 mode 2026-03-28 18:33:32 +08:00
Steven Dan
b64f28698f update hid protocol 2026-03-28 14:11:50 +08:00
19 changed files with 941 additions and 568 deletions

View File

@@ -161,32 +161,34 @@ struct lfs_config {
// Read a region in a block. Negative error codes are propagated
// to the user.
int (*read)(const struct lfs_config *c, lfs_block_t block,
int (* __attribute__((fptrgroup("local_block_device_read_fptr_grp"))) read)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size);
// Program a region in a block. The block must have previously
// been erased. Negative error codes are propagated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad.
int (*prog)(const struct lfs_config *c, lfs_block_t block,
int (* __attribute__((fptrgroup("local_block_device_prog_fptr_grp"))) prog)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size);
// Erase a block. A block must be erased before being programmed.
// The state of an erased block is undefined. Negative error codes
// are propagated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad.
int (*erase)(const struct lfs_config *c, lfs_block_t block);
int (* __attribute__((fptrgroup("local_block_device_erase_fptr_grp"))) erase)(const struct lfs_config *c, lfs_block_t block);
// Sync the state of the underlying block device. Negative error codes
// are propagated to the user.
int (*sync)(const struct lfs_config *c);
int (* __attribute__((fptrgroup("local_block_device_sync_fptr_grp"))) sync)(const struct lfs_config *c);
#ifdef LFS_THREADSAFE
// Lock the underlying block device. Negative error codes
// are propagated to the user.
LFS_FPTRGROUP("lfs_cfg_lock_fptr_grp")
int (*lock)(const struct lfs_config *c);
// Unlock the underlying block device. Negative error codes
// are propagated to the user.
LFS_FPTRGROUP("lfs_cfg_unlock_fptr_grp")
int (*unlock)(const struct lfs_config *c);
#endif
@@ -730,7 +732,7 @@ lfs_ssize_t lfs_fs_size(lfs_t *lfs);
// blocks are in use or how much of the storage is available.
//
// Returns a negative error code on failure.
int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);
int lfs_fs_traverse(lfs_t *lfs, int (* __attribute__((fptrgroup("lfs_cb_block_fptr_grp"))) cb)(void*, lfs_block_t), void *data);
#ifndef LFS_READONLY
// Attempt to make the filesystem consistent and ready for writing

View File

@@ -63,6 +63,13 @@ extern "C"
#endif
// xCORE fptrgroup attribute for stack analysis
#ifdef __xcore__
#define LFS_FPTRGROUP(name) __attribute__((fptrgroup(name)))
#else
#define LFS_FPTRGROUP(name)
#endif
// Macros, may be replaced by system specific wrappers. Arguments to these
// macros must not have side-effects as the macros can be removed for a smaller
// code footprint

View File

@@ -41,7 +41,7 @@ static inline void lfs_cache_zero(lfs_t *lfs, lfs_cache_t *pcache) {
pcache->block = LFS_BLOCK_NULL;
}
#pragma stackfunction 100
static int lfs_bd_read(lfs_t *lfs,
const lfs_cache_t *pcache, lfs_cache_t *rcache, lfs_size_t hint,
lfs_block_t block, lfs_off_t off,
@@ -125,7 +125,7 @@ static int lfs_bd_read(lfs_t *lfs,
return 0;
}
#pragma stackfunction 100
static int lfs_bd_cmp(lfs_t *lfs,
const lfs_cache_t *pcache, lfs_cache_t *rcache, lfs_size_t hint,
lfs_block_t block, lfs_off_t off,
@@ -153,7 +153,7 @@ static int lfs_bd_cmp(lfs_t *lfs,
return LFS_CMP_EQ;
}
#pragma stackfunction 100
static int lfs_bd_crc(lfs_t *lfs,
const lfs_cache_t *pcache, lfs_cache_t *rcache, lfs_size_t hint,
lfs_block_t block, lfs_off_t off, lfs_size_t size, uint32_t *crc) {
@@ -176,7 +176,7 @@ static int lfs_bd_crc(lfs_t *lfs,
}
#ifndef LFS_READONLY
#pragma stackfunction 100
static int lfs_bd_flush(lfs_t *lfs,
lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) {
if (pcache->block != LFS_BLOCK_NULL && pcache->block != LFS_BLOCK_INLINE) {
@@ -212,7 +212,7 @@ static int lfs_bd_flush(lfs_t *lfs,
#endif
#ifndef LFS_READONLY
#pragma stackfunction 100
static int lfs_bd_sync(lfs_t *lfs,
lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) {
lfs_cache_drop(lfs, rcache);
@@ -229,7 +229,7 @@ static int lfs_bd_sync(lfs_t *lfs,
#endif
#ifndef LFS_READONLY
#pragma stackfunction 100
static int lfs_bd_prog(lfs_t *lfs,
lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate,
lfs_block_t block, lfs_off_t off,
@@ -278,7 +278,7 @@ static int lfs_bd_prog(lfs_t *lfs,
#endif
#ifndef LFS_READONLY
#pragma stackfunction 100
static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) {
LFS_ASSERT(block < lfs->block_count);
int err = lfs->cfg->erase(lfs->cfg, block);
@@ -593,6 +593,7 @@ static void lfs_fs_prepsuperblock(lfs_t *lfs, bool needssuperblock);
#ifdef LFS_MIGRATE
static int lfs1_traverse(lfs_t *lfs,
LFS_FPTRGROUP("lfs_traverse_cb_fptr_grp")
int (*cb)(void*, lfs_block_t), void *data);
#endif
@@ -607,7 +608,7 @@ static lfs_soff_t lfs_file_size_(lfs_t *lfs, lfs_file_t *file);
static lfs_ssize_t lfs_fs_size_(lfs_t *lfs);
static int lfs_fs_traverse_(lfs_t *lfs,
int (*cb)(void *data, lfs_block_t block), void *data,
int (* __attribute__((fptrgroup("lfs_cb_block_fptr_grp"))) cb)(void *data, lfs_block_t block), void *data,
bool includeorphans);
static int lfs_deinit(lfs_t *lfs);
@@ -633,6 +634,7 @@ static void lfs_alloc_drop(lfs_t *lfs) {
}
#ifndef LFS_READONLY
__attribute__((fptrgroup("lfs_cb_block_fptr_grp")))
static int lfs_alloc_lookahead(void *p, lfs_block_t block) {
lfs_t *lfs = (lfs_t*)p;
lfs_block_t off = ((block - lfs->lookahead.start)
@@ -652,7 +654,7 @@ static int lfs_alloc_scan(lfs_t *lfs) {
//
// note we limit the lookahead buffer to at most the amount of blocks
// checkpointed, this prevents the math in lfs_alloc from underflowing
lfs->lookahead.start = (lfs->lookahead.start + lfs->lookahead.next)
lfs->lookahead.start = (lfs->lookahead.start + lfs->lookahead.next)
% lfs->block_count;
lfs->lookahead.next = 0;
lfs->lookahead.size = lfs_min(
@@ -859,7 +861,7 @@ static int lfs_dir_getread(lfs_t *lfs, const lfs_mdir_t *dir,
}
#ifndef LFS_READONLY
#pragma stackfunction 100
static int lfs_dir_traverse_filter(void *p,
lfs_tag_t tag, const void *buffer) {
lfs_tag_t *filtertag = p;
@@ -912,7 +914,7 @@ struct lfs_dir_traverse {
uint16_t end;
int16_t diff;
int (*cb)(void *data, lfs_tag_t tag, const void *buffer);
int (* __attribute__((fptrgroup("lfs_cb_tag_fptr_grp"))) cb)(void *data, lfs_tag_t tag, const void *buffer);
void *data;
lfs_tag_t tag;
@@ -920,13 +922,13 @@ struct lfs_dir_traverse {
struct lfs_diskoff disk;
};
#pragma stackfunction 200
static int lfs_dir_traverse(lfs_t *lfs,
const lfs_mdir_t *dir, lfs_off_t off, lfs_tag_t ptag,
const struct lfs_mattr *attrs, int attrcount,
lfs_tag_t tmask, lfs_tag_t ttag,
uint16_t begin, uint16_t end, int16_t diff,
int (*cb)(void *data, lfs_tag_t tag, const void *buffer), void *data) {
int (* __attribute__((fptrgroup("lfs_cb_tag_fptr_grp"))) cb)(void *data, lfs_tag_t tag, const void *buffer), void *data) {
// This function in inherently recursive, but bounded. To allow tool-based
// analysis without unnecessary code-cost we use an explicit stack
struct lfs_dir_traverse stack[LFS_DIR_TRAVERSE_DEPTH-1];
@@ -1116,18 +1118,18 @@ popped:
}
#endif
#pragma stackfunction 100
static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs,
lfs_mdir_t *dir, const lfs_block_t pair[2],
lfs_tag_t fmask, lfs_tag_t ftag, uint16_t *id,
int (*cb)(void *data, lfs_tag_t tag, const void *buffer), void *data) {
int (* __attribute__((fptrgroup("lfs_cb_tag_fptr_grp"))) cb)(void *data, lfs_tag_t tag, const void *buffer), void *data) {
// we can find tag very efficiently during a fetch, since we're already
// scanning the entire directory
lfs_stag_t besttag = -1;
// if either block address is invalid we return LFS_ERR_CORRUPT here,
// otherwise later writes to the pair could fail
if (lfs->block_count
if (lfs->block_count
&& (pair[0] >= lfs->block_count || pair[1] >= lfs->block_count)) {
return LFS_ERR_CORRUPT;
}
@@ -1462,6 +1464,7 @@ struct lfs_dir_find_match {
lfs_size_t size;
};
__attribute__((fptrgroup("lfs_cb_tag_fptr_grp")))
static int lfs_dir_find_match(void *data,
lfs_tag_t tag, const void *buffer) {
struct lfs_dir_find_match *name = data;
@@ -1924,6 +1927,7 @@ static int lfs_dir_split(lfs_t *lfs,
#endif
#ifndef LFS_READONLY
__attribute__((fptrgroup("lfs_cb_tag_fptr_grp")))
static int lfs_dir_commit_size(void *p, lfs_tag_t tag, const void *buffer) {
lfs_size_t *size = p;
(void)buffer;
@@ -1941,7 +1945,8 @@ struct lfs_dir_commit_commit {
#endif
#ifndef LFS_READONLY
#pragma stackfunction 100
__attribute__((fptrgroup("lfs_cb_tag_fptr_grp")))
static int lfs_dir_commit_commit(void *p, lfs_tag_t tag, const void *buffer) {
struct lfs_dir_commit_commit *commit = p;
return lfs_dir_commitattr(commit->lfs, commit->commit, tag, buffer);
@@ -1949,7 +1954,7 @@ static int lfs_dir_commit_commit(void *p, lfs_tag_t tag, const void *buffer) {
#endif
#ifndef LFS_READONLY
#pragma stackfunction 100
static bool lfs_dir_needsrelocation(lfs_t *lfs, lfs_mdir_t *dir) {
// If our revision count == n * block_cycles, we should force a relocation,
// this is how littlefs wear-levels at the metadata-pair level. Note that we
@@ -1963,7 +1968,7 @@ static bool lfs_dir_needsrelocation(lfs_t *lfs, lfs_mdir_t *dir) {
#endif
#ifndef LFS_READONLY
#pragma stackfunction 100
static int lfs_dir_compact(lfs_t *lfs,
lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount,
lfs_mdir_t *source, uint16_t begin, uint16_t end) {
@@ -2137,7 +2142,7 @@ relocate:
#endif
#ifndef LFS_READONLY
#pragma stackfunction 100
static int lfs_dir_splittingcompact(lfs_t *lfs, lfs_mdir_t *dir,
const struct lfs_mattr *attrs, int attrcount,
lfs_mdir_t *source, uint16_t begin, uint16_t end) {
@@ -2247,7 +2252,7 @@ static int lfs_dir_splittingcompact(lfs_t *lfs, lfs_mdir_t *dir,
#endif
#ifndef LFS_READONLY
#pragma stackfunction 100
static int lfs_dir_relocatingcommit(lfs_t *lfs, lfs_mdir_t *dir,
const lfs_block_t pair[2],
const struct lfs_mattr *attrs, int attrcount,
@@ -2421,7 +2426,7 @@ fixmlist:;
#endif
#ifndef LFS_READONLY
#pragma stackfunction 100
static int lfs_dir_orphaningcommit(lfs_t *lfs, lfs_mdir_t *dir,
const struct lfs_mattr *attrs, int attrcount) {
// check for any inline files that aren't RAM backed and
@@ -2615,7 +2620,7 @@ static int lfs_dir_orphaningcommit(lfs_t *lfs, lfs_mdir_t *dir,
#endif
#ifndef LFS_READONLY
#pragma stackfunction 100
static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
const struct lfs_mattr *attrs, int attrcount) {
int orphans = lfs_dir_orphaningcommit(lfs, dir, attrs, attrcount);
@@ -2640,7 +2645,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
/// Top level directory operations ///
#ifndef LFS_READONLY
#pragma stackfunction 100
static int lfs_mkdir_(lfs_t *lfs, const char *path) {
// deorphan if we haven't yet, needed at most once after poweron
int err = lfs_fs_forceconsistency(lfs);
@@ -2736,7 +2741,7 @@ static int lfs_mkdir_(lfs_t *lfs, const char *path) {
return 0;
}
#endif
#pragma stackfunction 100
static int lfs_dir_open_(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
lfs_stag_t tag = lfs_dir_find(lfs, &dir->m, &path, NULL);
if (tag < 0) {
@@ -2781,7 +2786,7 @@ static int lfs_dir_open_(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
return 0;
}
#pragma stackfunction 100
static int lfs_dir_close_(lfs_t *lfs, lfs_dir_t *dir) {
// remove from list of mdirs
lfs_mlist_remove(lfs, (struct lfs_mlist *)dir);
@@ -2789,7 +2794,7 @@ static int lfs_dir_close_(lfs_t *lfs, lfs_dir_t *dir) {
return 0;
}
#pragma stackfunction 100
static int lfs_dir_read_(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
memset(info, 0, sizeof(*info));
@@ -2835,7 +2840,7 @@ static int lfs_dir_read_(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
return true;
}
#pragma stackfunction 100
static int lfs_dir_seek_(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
// simply walk from head dir
int err = lfs_dir_rewind_(lfs, dir);
@@ -3042,7 +3047,7 @@ relocate:
static int lfs_ctz_traverse(lfs_t *lfs,
const lfs_cache_t *pcache, lfs_cache_t *rcache,
lfs_block_t head, lfs_size_t size,
int (*cb)(void*, lfs_block_t), void *data) {
int (* __attribute__((fptrgroup("lfs_cb_block_fptr_grp"))) cb)(void*, lfs_block_t), void *data) {
if (size == 0) {
return 0;
}
@@ -3285,7 +3290,7 @@ static int lfs_file_close_(lfs_t *lfs, lfs_file_t *file) {
#ifndef LFS_READONLY
#pragma stackfunction 100
static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) {
while (true) {
// just relocate what exists into new block
@@ -3451,7 +3456,7 @@ relocate:
}
#ifndef LFS_READONLY
#pragma stackfunction 100
static int lfs_file_sync_(lfs_t *lfs, lfs_file_t *file) {
if (file->flags & LFS_F_ERRED) {
// it's not safe to do anything if our file errored
@@ -3593,7 +3598,7 @@ static lfs_ssize_t lfs_file_read_(lfs_t *lfs, lfs_file_t *file,
#ifndef LFS_READONLY
#pragma stackfunction 100
static lfs_ssize_t lfs_file_flushedwrite(lfs_t *lfs, lfs_file_t *file,
const void *buffer, lfs_size_t size) {
const uint8_t *data = buffer;
@@ -3678,7 +3683,7 @@ relocate:
return size;
}
#pragma stackfunction 100
static lfs_ssize_t lfs_file_write_(lfs_t *lfs, lfs_file_t *file,
const void *buffer, lfs_size_t size) {
LFS_ASSERT((file->flags & LFS_O_WRONLY) == LFS_O_WRONLY);
@@ -3723,7 +3728,7 @@ static lfs_ssize_t lfs_file_write_(lfs_t *lfs, lfs_file_t *file,
}
#endif
#pragma stackfunction 100
static lfs_soff_t lfs_file_seek_(lfs_t *lfs, lfs_file_t *file,
lfs_soff_t off, int whence) {
// find new pos
@@ -3782,7 +3787,7 @@ static lfs_soff_t lfs_file_seek_(lfs_t *lfs, lfs_file_t *file,
}
#ifndef LFS_READONLY
#pragma stackfunction 100
static int lfs_file_truncate_(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
LFS_ASSERT((file->flags & LFS_O_WRONLY) == LFS_O_WRONLY);
@@ -4679,7 +4684,7 @@ static int lfs_unmount_(lfs_t *lfs) {
/// Filesystem filesystem operations ///
#pragma stackfunction 100
static int lfs_fs_stat_(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {
// if the superblock is up-to-date, we must be on the most recent
// minor version of littlefs
@@ -4720,9 +4725,9 @@ static int lfs_fs_stat_(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {
return 0;
}
#pragma stackfunction 100
int lfs_fs_traverse_(lfs_t *lfs,
int (*cb)(void *data, lfs_block_t block), void *data,
int (* __attribute__((fptrgroup("lfs_cb_block_fptr_grp"))) cb)(void *data, lfs_block_t block), void *data,
bool includeorphans) {
// iterate over metadata pairs
lfs_mdir_t dir = {.tail = {0, 1}};
@@ -5200,6 +5205,7 @@ static int lfs_fs_mkconsistent_(lfs_t *lfs) {
}
#endif
__attribute__((fptrgroup("lfs_cb_block_fptr_grp")))
static int lfs_fs_size_count(void *p, lfs_block_t block) {
(void)block;
lfs_size_t *size = p;
@@ -5550,7 +5556,9 @@ static int lfs1_dir_next(lfs_t *lfs, lfs1_dir_t *dir, lfs1_entry_t *entry) {
}
/// littlefs v1 specific operations ///
int lfs1_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) {
int lfs1_traverse(lfs_t *lfs,
LFS_FPTRGROUP("lfs_traverse_cb_fptr_grp")
int (*cb)(void*, lfs_block_t), void *data) {
if (lfs_pair_isnull(lfs->lfs1->root)) {
return 0;
}
@@ -6196,7 +6204,7 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
}
#ifndef LFS_READONLY
#pragma stackfunction 100
int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
int err = LFS_LOCK(lfs->cfg);
if (err) {
@@ -6459,7 +6467,7 @@ lfs_ssize_t lfs_fs_size(lfs_t *lfs) {
return res;
}
int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void *, lfs_block_t), void *data) {
int lfs_fs_traverse(lfs_t *lfs, int (* __attribute__((fptrgroup("lfs_cb_block_fptr_grp"))) cb)(void *, lfs_block_t), void *data) {
int err = LFS_LOCK(lfs->cfg);
if (err) {
return err;
@@ -6552,4 +6560,3 @@ int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg) {
return err;
}
#endif

View File

@@ -579,7 +579,7 @@ void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, NULLABLE_RESOURCE(c
unsigned char hidReportDescriptorLengthLo = hidReportDescriptorLength & 0xFF;
unsigned char hidReportDescriptorLengthHi = (hidReportDescriptorLength & 0xFF00) >> 8;
#if( AUDIO_CLASS == 1 )
#if( AUDIO_CLASS == 1 && HID_CONTROLS_UAC1 == 1)
cfgDesc_Audio1[USB_HID_DESCRIPTOR_OFFSET + HID_DESCRIPTOR_LENGTH_FIELD_OFFSET ] = hidReportDescriptorLengthLo;
cfgDesc_Audio1[USB_HID_DESCRIPTOR_OFFSET + HID_DESCRIPTOR_LENGTH_FIELD_OFFSET + 1] = hidReportDescriptorLengthHi;
#endif

View File

@@ -2392,12 +2392,18 @@ const unsigned num_freqs_a1 = MAX(3, (0
* - xua_hid_endpoint_descriptor_contents.h and
* - xua_hid_interface_descriptor_contents.h
*/
#if (HID_CONTROLS_UAC1 == 1)
#define HID_INTERFACE_BYTES ( 9 + 9 + (7 * (1 + HID_OUT_REQUIRED))) // always IN
#define HID_INTERFACES_A1 1
#else
#define HID_INTERFACE_BYTES 0
#define HID_INTERFACES_A1 0
#endif
#else
#define HID_INTERFACE_BYTES 0
#define HID_INTERFACES_A1 0
#endif
/* Total number of bytes returned for the class-specific AudioControl interface descriptor.
* Includes the combined length of this descriptor header and all Unit and Terminal descriptors
@@ -2409,13 +2415,13 @@ const unsigned num_freqs_a1 = MAX(3, (0
#define STREAMING_INTERFACES (INPUT_INTERFACES_A1 + OUTPUT_INTERFACES_A1)
/* Number of interfaces for Audio 1.0 (+1 for control ) */
/* Note, this is different than INTERFACE_COUNT since we dont support items such as MIDI, iAP etc in UAC1 mode */
#define NUM_INTERFACES_A1 (1 + INPUT_INTERFACES_A1 + OUTPUT_INTERFACES_A1 + MIDI_INTERFACES_A1 + NUM_CONTROL_USB_INTERFACES + DFU_INTERFACES_A1 + HID_INTERFACES_A1)
/* Note, this is different that INTERFACE_COUNT since we dont support items such as MIDI, iAP etc in UAC1 mode */
#define NUM_INTERFACES_A1 (1 + INPUT_INTERFACES_A1 + OUTPUT_INTERFACES_A1 + NUM_CONTROL_USB_INTERFACES + DFU_INTERFACES_A1 + HID_INTERFACES_A1)
#if ((NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)) && (XUA_SYNCMODE == XUA_SYNCMODE_ASYNC)
#define CFG_TOTAL_LENGTH_A1 (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + (OUTPUT_INTERFACES_A1 * (58 + num_freqs_a1 * 3)) + MIDI_INTERFACE_BYTES + CONTROL_INTERFACE_BYTES + DFU_INTERFACE_BYTES + HID_INTERFACE_BYTES)
#define CFG_TOTAL_LENGTH_A1 (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + (OUTPUT_INTERFACES_A1 * (58 + num_freqs_a1 * 3)) + CONTROL_INTERFACE_BYTES + DFU_INTERFACE_BYTES + HID_INTERFACE_BYTES)
#else
#define CFG_TOTAL_LENGTH_A1 (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + (OUTPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + MIDI_INTERFACE_BYTES + CONTROL_INTERFACE_BYTES + DFU_INTERFACE_BYTES + HID_INTERFACE_BYTES)
#define CFG_TOTAL_LENGTH_A1 (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + (OUTPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + CONTROL_INTERFACE_BYTES + DFU_INTERFACE_BYTES + HID_INTERFACE_BYTES)
#endif
#define INTERFACE_DESCRIPTOR_BYTES (9)
@@ -2435,7 +2441,7 @@ const unsigned num_freqs_a1 = MAX(3, (0
#endif
#if XUA_OR_STATIC_HID_ENABLED
#define USB_HID_DESCRIPTOR_OFFSET (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + (OUTPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + MIDI_INTERFACE_BYTES + CONTROL_INTERFACE_BYTES + DFU_INTERFACE_BYTES + INTERFACE_DESCRIPTOR_BYTES)
#define USB_HID_DESCRIPTOR_OFFSET (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + (OUTPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + CONTROL_INTERFACE_BYTES + DFU_INTERFACE_BYTES + 9 + 9 )
#endif
#define CHARIFY_SR(x) (x & 0xff),((x & 0xff00)>> 8),((x & 0xff0000)>> 16)

View File

@@ -83,7 +83,8 @@ XUD_Result_t HidInterfaceClassRequests(
#endif
}
if (buffer[1] == 0x77 && buffer[2] >= 0x82)
if (buffer[1] == 0x77 && ((buffer[2] >= 0x82) || (buffer[2] == 0x5b)))
{
process_send_params(&buffer[1], datalength - 1);
}

View File

@@ -38,7 +38,7 @@ endif()
# Firmware version (maps to BCD_DEVICE_J.M.N in USB descriptor)
set(FW_VER_J 1)
set(FW_VER_M 0)
set(FW_VER_N 2)
set(FW_VER_N 9)
set(FW_VERSION "v${FW_VER_J}.${FW_VER_M}.${FW_VER_N}")
set(SW_USB_AUDIO_FLAGS ${EXTRA_BUILD_FLAGS} -Os
@@ -54,8 +54,7 @@ set(SW_USB_AUDIO_FLAGS ${EXTRA_BUILD_FLAGS} -Os
-DBCD_DEVICE_M=${FW_VER_M}
-DBCD_DEVICE_N=${FW_VER_N}
-D${CODEC_IC}
-DWINDOWS_OS_DESCRIPTOR_SUPPORT
-DDEBUG_PRINT_ENABLE=0)
-DWINDOWS_OS_DESCRIPTOR_SUPPORT)
set(SW_USB_FACT_FLAGS ${EXTRA_BUILD_FLAGS} -Os
-report
@@ -70,8 +69,7 @@ set(SW_USB_FACT_FLAGS ${EXTRA_BUILD_FLAGS} -Os
-DBCD_DEVICE_M=5
-DBCD_DEVICE_N=6
-D${CODEC_IC}
-DWINDOWS_OS_DESCRIPTOR_SUPPORT
-DDEBUG_PRINT_ENABLE=0)
-DWINDOWS_OS_DESCRIPTOR_SUPPORT)
@@ -82,13 +80,15 @@ set(APP_COMPILER_FLAGS_f5_music_uac1 ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC
-DAUDIO_CLASS=1
-DMIN_FREQ=48000
-DMAX_FREQ=48000
-DMCLK_441=512*44100
-DMCLK_48=512*48000
-DUAC1_MODE=1
-DF5_MUSIC_UAC1=1
-DUSE_EX3D
#-DUSE_EX3D
-DMIXER=0
#-ldnr_50ms
#-DDNR_ENABLE=1
-llib_ex3d_all
#-llib_ex3d_all
-DEQ_EN=1
-DEX3D_SF_NUM=3
-DNUM_USB_CHAN_OUT=8
@@ -100,14 +100,15 @@ set(APP_COMPILER_FLAGS_f5_music_uac1 ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC
-DSTREAM_FORMAT_INPUT_1_RESOLUTION_BITS=16
-DSTREAM_FORMAT_INPUT_2_RESOLUTION_BITS=16
-DSTREAM_FORMAT_INPUT_3_RESOLUTION_BITS=16
-DNUM_EX3D_CHAN_OUT=2
#-DNUM_EX3D_CHAN_OUT=2
-DMIN_VOLUME=0xE000
-DINPUT_VOLUME_CONTROL=1
-DOUTPUT_VOLUME_CONTROL=1
-DINPUT_VOLUME_CONTROL=0
-DOUTPUT_VOLUME_CONTROL=0
-DDEBUG_MEMORY_LOG_ENABLED=1
-DXUA_DFU_EN=0
-DIR_SWITCHING_MODE
-DHID_CONTROLS=0)
-DHID_CONTROLS_UAC1=1
#-DIR_SWITCHING_MODE
-DHID_CONTROLS=1)
@@ -141,6 +142,12 @@ set(APP_COMPILER_FLAGS_f1_music_uac2 ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC
-DMIN_FREQ=44100
-DMAX_FREQ=192000
-DF1_MUSIC_UAC2=1
-DSTREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS=24
-DSTREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS=24
-DSTREAM_FORMAT_INPUT_1_RESOLUTION_BITS=24
-DSTREAM_FORMAT_INPUT_2_RESOLUTION_BITS=24
-DINPUT_FORMAT_COUNT=1
-DOUTPUT_FORMAT_COUNT=1
#-DUSE_EX3D
-DMIXER=0
-DUAC2_MODE=1
@@ -173,6 +180,10 @@ set(APP_COMPILER_FLAGS_f3_f4_fps_uac2 ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
-llib_ex3d_all
-DEQ_EN=1
-DDNR_ENABLE=1
-DSTREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS=16
-DSTREAM_FORMAT_INPUT_1_RESOLUTION_BITS=16
-DINPUT_FORMAT_COUNT=1
-DOUTPUT_FORMAT_COUNT=1
-DEX3D_SF_NUM=3
-DNUM_USB_CHAN_OUT=8
-DNUM_USB_CHAN_IN=2

View File

@@ -52,7 +52,8 @@
<Port Location="XS1_PORT_1K" Name="PORT_I2S_DAC0"/> <!-- orig 1P, Synido 1K -->
<Port Location="XS1_PORT_1A" Name="PORT_I2S_ADC0"/> <!-- orig 1I, Synido 1A -->
<Port Location="XS1_PORT_4D" Name="PORT_CTL_MUTE"/> <!-- Tile1 4D0 -->
<Port Location="XS1_PORT_4A" Name="PORT_CTL_MUTE"/> <!-- Tile1 4D0 -->
<Port Location="XS1_PORT_4D" Name="PORT_CTL_DET"/> <!-- Tile1 4D0 -->
</Tile>
</Node>

View File

@@ -189,6 +189,113 @@
/*
* New spispec for QF60 board
* */
#define FL_QUADDEVICE_GD25Q32E \
{ \
0, /* XT25F16F - Just specify 0 as flash_id */ \
256, /* page size */ \
16384, /* num pages */ \
3, /* address size */ \
4, /* log2 clock divider */ \
0x9F, /* QSPI_RDID */ \
0, /* id dummy bytes */ \
3, /* id size in bytes */ \
0xc84016, /* device id */ \
0x20, /* QSPI_SE */ \
4096, /* Sector erase is always 4KB */ \
0x06, /* QSPI_WREN */ \
0x04, /* QSPI_WRDI */ \
PROT_TYPE_SR, /* Protection via SR */ \
{{0x0,0x00},{0,0}}, /* QSPI_SP, QSPI_SU */ \
0x02, /* QSPI_PP */ \
0xEB, /* QSPI_READ_FAST */ \
1, /* 1 read dummy byte */ \
SECTOR_LAYOUT_REGULAR, /* mad sectors */ \
{4096,{0,{0}}}, /* regular sector sizes */ \
0x05, /* QSPI_RDSR */ \
0x01, /* QSPI_WRSR */ \
0x01, /* QSPI_WIP_BIT_MASK */ \
}
#define FL_QUADDEVICE_ZB25VQ32D \
{ \
0, /* XT25F16F - Just specify 0 as flash_id */ \
256, /* page size */ \
16384, /* num pages */ \
3, /* address size */ \
4, /* log2 clock divider */ \
0x9F, /* QSPI_RDID */ \
0, /* id dummy bytes */ \
3, /* id size in bytes */ \
0x5E8016, /* device id */ \
0x20, /* QSPI_SE */ \
4096, /* Sector erase is always 4KB */ \
0x06, /* QSPI_WREN */ \
0x04, /* QSPI_WRDI */ \
PROT_TYPE_SR, /* Protection via SR */ \
{{0x0,0x00},{0,0}}, /* QSPI_SP, QSPI_SU */ \
0x02, /* QSPI_PP */ \
0xEB, /* QSPI_READ_FAST */ \
1, /* 1 read dummy byte */ \
SECTOR_LAYOUT_REGULAR, /* mad sectors */ \
{4096,{0,{0}}}, /* regular sector sizes */ \
0x05, /* QSPI_RDSR */ \
0x01, /* QSPI_WRSR */ \
0x01, /* QSPI_WIP_BIT_MASK */ \
}
#define FL_QUADDEVICE_PY25Q32SH \
{ \
0, /* XT25F16F - Just specify 0 as flash_id */ \
256, /* page size */ \
16384, /* num pages */ \
3, /* address size */ \
4, /* log2 clock divider */ \
0x9F, /* QSPI_RDID */ \
0, /* id dummy bytes */ \
3, /* id size in bytes */ \
0x856016, /* device id */ \
0x20, /* QSPI_SE */ \
4096, /* Sector erase is always 4KB */ \
0x06, /* QSPI_WREN */ \
0x04, /* QSPI_WRDI */ \
PROT_TYPE_SR, /* Protection via SR */ \
{{0x0,0x00},{0,0}}, /* QSPI_SP, QSPI_SU */ \
0x02, /* QSPI_PP */ \
0xEB, /* QSPI_READ_FAST */ \
1, /* 1 read dummy byte */ \
SECTOR_LAYOUT_REGULAR, /* mad sectors */ \
{4096,{0,{0}}}, /* regular sector sizes */ \
0x05, /* QSPI_RDSR */ \
0x01, /* QSPI_WRSR */ \
0x01, /* QSPI_WIP_BIT_MASK */ \
}
#define FL_QUADDEVICE_PY25Q32H \
{ \
0, /* XT25F16F - Just specify 0 as flash_id */ \
256, /* page size */ \
16384, /* num pages */ \
3, /* address size */ \
4, /* log2 clock divider */ \
0x9F, /* QSPI_RDID */ \
0, /* id dummy bytes */ \
3, /* id size in bytes */ \
0x852016, /* device id */ \
0x20, /* QSPI_SE */ \
4096, /* Sector erase is always 4KB */ \
0x06, /* QSPI_WREN */ \
0x04, /* QSPI_WRDI */ \
PROT_TYPE_SR, /* Protection via SR */ \
{{0x0,0x00},{0,0}}, /* QSPI_SP, QSPI_SU */ \
0x02, /* QSPI_PP */ \
0xEB, /* QSPI_READ_FAST */ \
1, /* 1 read dummy byte */ \
SECTOR_LAYOUT_REGULAR, /* mad sectors */ \
{4096,{0,{0}}}, /* regular sector sizes */ \
0x05, /* QSPI_RDSR */ \
0x01, /* QSPI_WRSR */ \
0x01, /* QSPI_WIP_BIT_MASK */ \
}
#define FL_QUADDEVICE_XT25F16F \
{ \
@@ -362,7 +469,7 @@
// DFU_FLASH_DEVICE is a comma-separated list of flash spec structures
// This define is used in lib_xua/lib_xua/src/dfu/flashlib_user.c
#define DFU_FLASH_DEVICE FL_QUADDEVICE_XT25F16F, FL_QUADDEVICE_WINBOND_W25Q16JW, FL_QUADDEVICE_UC25HQ16B, FL_QUADDEVICE_WINBOND_W25Q32JVxxxM, FL_QUADDEVICE_MX25R3235, FL_QUADDEVICE_MX25L160E
#define DFU_FLASH_DEVICE FL_QUADDEVICE_GD25Q32E, FL_QUADDEVICE_ZB25VQ32D, FL_QUADDEVICE_PY25Q32SH, FL_QUADDEVICE_PY25Q32H, FL_QUADDEVICE_XT25F16F, FL_QUADDEVICE_WINBOND_W25Q16JW, FL_QUADDEVICE_UC25HQ16B, FL_QUADDEVICE_WINBOND_W25Q32JVxxxM, FL_QUADDEVICE_MX25R3235, FL_QUADDEVICE_MX25L160E
//:
#include "user_main.h"

View File

@@ -107,6 +107,10 @@ unsigned g_dac_mode = 10;
unsigned g_new_dac_mode = 0;
unsigned g_samfreq = 48000;
unsigned g_dsd_mode = 0;
// mic detect events: mute_handler (tile[1]) → button_task (tile[0])
#define MIC_DET_MUTE 1 // mic插入或全拔出立即mute
#define MIC_DET_UNMUTE 2 // 插入1s后恢复音量
unsafe chanend uc_audiohw; // tile[1] end: AudioHwConfig → button_task (tile[0])
#if HID_DFU_EN
unsafe streaming chanend uc_dfu; // tile[1] send end: hid_button_task → button_task (tile[0])
@@ -150,6 +154,7 @@ port p_sda = PORT_I2C_SDA;
//out port p_htr3235_sdb = PORT_HTR3236_SDB; /* 连接到HTR3236的SDB引脚用于控制其电源状态 */
out port p_ctl_mute = PORT_CTL_MUTE;
in port p_ctl_det = PORT_CTL_DET;
/* Board setup for XU316 MC Audio (1v1) */
@@ -274,6 +279,7 @@ in port p_button_ai71_onoff = PORT_BUTTON_AI71_ONOFF; // 1M
#define TIMER_PERIOD (100000)
#define FACTORY_RESET_HOLD_TICKS 3000 // 3000 × 1ms = 3秒
#define FACTORY_RESET_BLINK_TICKS 400 // 每相400ms
#define MUTE_BLINK_HALF_PERIOD 500 // mute LED blink half period 250ms
#define BTN_COMBO_DELAY_TICKS 40 // 单键去抖/组合检测窗口50ms
unsigned g_windows_detect_done = 0;
@@ -326,6 +332,7 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
#if HID_DFU_EN
, streaming chanend c_dfu_rx
#endif
, chanend c_mic_det
)
{
//hwtimer_t timer = hwtimer_alloc();
@@ -395,6 +402,7 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
unsigned flag_mic_mute = 0;
unsigned flag_hp_mute = 0;
unsigned mic_det_muted = 0; // mic检测导致的mute不影响LED和g_mic_volume_level
unsigned push_button_mic_mute_state_old = 1; // Active low
unsigned push_button_hp_mute_state_old = 1; // Active low
@@ -403,6 +411,8 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
unsigned factory_reset_hold_count = 0; // 两键同时按住计数×1ms
unsigned factory_reset_blink_state = 0; // 0=空闲1-6=闪烁相位
unsigned factory_reset_blink_tick = 0; // 当前相位内计数
unsigned mic_mute_blink_tick = 0;
unsigned hp_mute_blink_tick = 0;
// 组合键去抖:单键动作延迟 BTN_COMBO_DELAY_TICKS 后触发,期间若另一键也按下则切换为组合模式
unsigned btn_music_hold_ticks = 0; // music键连续按住计数
unsigned btn_game_hold_ticks = 0; // game键连续按住计数
@@ -466,7 +476,7 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
else
{
if (saved_mode >= 2) {
SetRoleSwitchFlag(MODE_F6_F7_FPS_UAC1);
SetRoleSwitchFlag(MODE_F5_MUSIC_UAC1);
device_reboot();
while (1);
}
@@ -480,7 +490,7 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
#if defined(F5_MUSIC_UAC1)
saved_mode = 1; // f5: default music mode
#else
saved_mode = 0; // f6/f7: default off
saved_mode = 1; // f6/f7: default off
#endif
save_value(path, saved_mode);
debug_printf("Saved game_mode to flash: %d\n", saved_mode);
@@ -607,7 +617,7 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
// 若mic_mute已从flash恢复为1则此处先以正常gain调用再用mute覆盖
mic_volume(codec_adc_pga_gain_reg_value);
{
int mic_led_count = flag_mic_mute ? 0 : mic_gain_to_led[codec_adc_pga_gain_reg_value];
int mic_led_count = flag_mic_mute ? 15 : mic_gain_to_led[codec_adc_pga_gain_reg_value];
for(int i = 0; i < 15; i++)
{
if (i < mic_led_count)
@@ -620,6 +630,7 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
if(flag_mic_mute) {
mic_volume(0);
g_mic_volume_level = 0;
mic_mute_blink_tick = 1;
}
if ((g_monitor_switch == 1) && !flag_mic_mute && codec_adc_pga_gain_reg_value >= 2) {
@@ -634,7 +645,7 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
else
dac_volume(dac_level - DAC_LEVEL_MAX);
{
int dac_led_count = flag_hp_mute ? 0 : dac_gain_to_led[dac_level];
int dac_led_count = flag_hp_mute ? 15 : dac_gain_to_led[dac_level];
for(int i = 0; i < 15; i++)
{
if (i < dac_led_count)
@@ -647,6 +658,7 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
if(flag_hp_mute) {
unsafe { NAU88C22_REGWRITE(0x0034, 0x0000, (client interface i2c_master_if)i_i2c_client); }
g_volume_level = 0;
hp_mute_blink_tick = 1;
}
// Initialize mode button LEDs: at most one may be lit at a time
led_off(&led_ctx, LED_MUSIC);
@@ -859,6 +871,7 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
debug_printf("SampRate->tile0: %uHz dsd=%u\n", new_samfreq, new_dsd_mode);
unsafe {
#if !UAC1_MODE
switch (new_samfreq) {
case 192000:
case 176400:
@@ -881,6 +894,7 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
NAU88C22_REGWRITE(0x002C, 0x0082, (client interface i2c_master_if)i_i2c_client);
break;
}
#endif
#if 0
unsigned val;
@@ -935,6 +949,24 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
}
#endif
case c_mic_det :> unsigned mic_det_cmd:
{
if (mic_det_cmd == MIC_DET_MUTE) {
mic_det_muted = 1;
// 仅mute硬件不改变g_mic_volume_level和LED
mic_volume(0);
debug_printf("mic_det: mute (det)\n");
} else if (mic_det_cmd == MIC_DET_UNMUTE) {
mic_det_muted = 0;
// 恢复音量但如果用户手动mute了则不恢复
if (!flag_mic_mute) {
mic_volume(codec_adc_pga_gain_reg_value);
debug_printf("mic_det: unmute -> pga=%d\n", codec_adc_pga_gain_reg_value);
}
}
break;
}
case tmr when timerafter(time) :> void :
{
//hwtimer_change_trigger_time(timer, hwtimer_get_time(timer) + KEY_POLLING_INTERVAL);
@@ -993,26 +1025,26 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
int factory_combo_is_down = ( music_is_down && game_is_down);
// 更新各键连续按住计数(断开则清零,用于去抖和窗口判断)
if (music_is_down && !factory_combo_is_down)
{
if (btn_music_hold_ticks < 0xFFFFu) btn_music_hold_ticks++;
if (music_is_down && !factory_combo_is_down)
{
if (btn_music_hold_ticks < 0xFFFFu) btn_music_hold_ticks++;
debug_printf("btn_music_hold_ticks=%d\n", btn_music_hold_ticks);
}
else
{
btn_music_hold_ticks = 0;
else
{
btn_music_hold_ticks = 0;
}
if (game_is_down && !factory_combo_is_down)
{
if (btn_game_hold_ticks < 0xFFFFu)
{
btn_game_hold_ticks++;
if (game_is_down && !factory_combo_is_down)
{
if (btn_game_hold_ticks < 0xFFFFu)
{
btn_game_hold_ticks++;
}
debug_printf("btn_game_hold_ticks=%d\n", btn_game_hold_ticks);
}
else
{
btn_game_hold_ticks = 0;
else
{
btn_game_hold_ticks = 0;
}
// 场景1两键同时按住参照 fosi_ds1 else-if 结构)
@@ -1375,17 +1407,18 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
{
mic_volume(0);
g_mic_volume_level = 0;
current_mic_led_pos = mic_gain_to_led[codec_adc_pga_gain_reg_value] - 1;
for(int i = 0; i <= current_mic_led_pos; i++)
{
if ((i < 15) && (i >= 0))
led_off(&led_ctx, led_l_physical_map[i]);
}
for(int i = 0; i < 15; i++)
led_on(&led_ctx, led_l_physical_map[i]);
mic_mute_blink_tick = 1;
}
else
{
mic_volume(codec_adc_pga_gain_reg_value);
if (!mic_det_muted)
mic_volume(codec_adc_pga_gain_reg_value);
g_mic_volume_level = (codec_adc_pga_gain_reg_value <= 37) ? codec_adc_pga_gain_reg_value : 37;
mic_mute_blink_tick = 0;
for(int i = 0; i < 15; i++)
led_off(&led_ctx, led_l_physical_map[i]);
current_mic_led_pos = mic_gain_to_led[codec_adc_pga_gain_reg_value] - 1;
for(int i = 0; i <= current_mic_led_pos; i++)
{
@@ -1424,7 +1457,9 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
uint8_t old_led_count = mic_gain_to_led[codec_adc_pga_gain_reg_value];
// 增加音量
mic_volume(++codec_adc_pga_gain_reg_value);
++codec_adc_pga_gain_reg_value;
if (!mic_det_muted)
mic_volume(codec_adc_pga_gain_reg_value);
g_mic_volume_level = (codec_adc_pga_gain_reg_value <= 37) ? codec_adc_pga_gain_reg_value : 37;
debug_printf("volume up %d\n", codec_adc_pga_gain_reg_value);
save_value(mic_vol_path, codec_adc_pga_gain_reg_value);
@@ -1442,7 +1477,9 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
uint8_t old_led_count = mic_gain_to_led[codec_adc_pga_gain_reg_value];
// 减小音量
mic_volume(--codec_adc_pga_gain_reg_value);
--codec_adc_pga_gain_reg_value;
if (!mic_det_muted)
mic_volume(codec_adc_pga_gain_reg_value);
g_mic_volume_level = (codec_adc_pga_gain_reg_value <= 37) ? codec_adc_pga_gain_reg_value : 37;
debug_printf("volume down %d\n", codec_adc_pga_gain_reg_value);
save_value(mic_vol_path, codec_adc_pga_gain_reg_value);
@@ -1613,12 +1650,9 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
{
unsafe { NAU88C22_REGWRITE(0x0034, 0x0000, (client interface i2c_master_if)i_i2c_client); }
g_volume_level = 0;
current_mic_led_pos = dac_gain_to_led[dac_level] - 1;
for(int i = 0; i <= current_mic_led_pos; i++)
{
if ((i < 15) && (i >= 0))
led_off(&led_ctx, led_d_physical_map[i]);
}
for(int i = 0; i < 15; i++)
led_on(&led_ctx, led_d_physical_map[i]);
hp_mute_blink_tick = 1;
}
else
{
@@ -1627,6 +1661,9 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
else
dac_volume(dac_level - DAC_LEVEL_MAX);
g_volume_level = dac_level;
hp_mute_blink_tick = 0;
for(int i = 0; i < 15; i++)
led_off(&led_ctx, led_d_physical_map[i]);
current_mic_led_pos = dac_gain_to_led[dac_level] - 1;
for(int i = 0; i <= current_mic_led_pos; i++)
{
@@ -1635,6 +1672,27 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
}
}
// mute blink: 250ms on / 250ms off
if(mic_mute_blink_tick > 0)
{
mic_mute_blink_tick++;
if(mic_mute_blink_tick >= MUTE_BLINK_HALF_PERIOD * 2)
mic_mute_blink_tick = 1;
if(mic_mute_blink_tick == 1)
for(int i = 0; i < 15; i++) led_on(&led_ctx, led_l_physical_map[i]);
else if(mic_mute_blink_tick == MUTE_BLINK_HALF_PERIOD + 1)
for(int i = 0; i < 15; i++) led_off(&led_ctx, led_l_physical_map[i]);
}
if(hp_mute_blink_tick > 0)
{
hp_mute_blink_tick++;
if(hp_mute_blink_tick >= MUTE_BLINK_HALF_PERIOD * 2)
hp_mute_blink_tick = 1;
if(hp_mute_blink_tick == 1)
for(int i = 0; i < 15; i++) led_on(&led_ctx, led_d_physical_map[i]);
else if(hp_mute_blink_tick == MUTE_BLINK_HALF_PERIOD + 1)
for(int i = 0; i < 15; i++) led_off(&led_ctx, led_d_physical_map[i]);
}
led_update_all(&led_ctx);
#endif
@@ -1685,7 +1743,8 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
new_led_count = 0;
} else {
codec_adc_pga_gain_reg_value = new_mic_level;
mic_volume(codec_adc_pga_gain_reg_value);
if (!mic_det_muted)
mic_volume(codec_adc_pga_gain_reg_value);
new_led_count = mic_gain_to_led[codec_adc_pga_gain_reg_value];
}
save_value(mic_vol_path, (unsigned char)codec_adc_pga_gain_reg_value);
@@ -1863,6 +1922,14 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
}
#endif
#if UAC1_MODE == 1
if (host_os == OS_WIN) {
unsigned flag = (saved_mode <= 1) ? MODE_F1_MUSIC_UAC2 : MODE_F3_F4_FPS_UAC2;
SetRoleSwitchFlag(flag);
device_reboot();
while (1);
}
#endif
break;
}
}
@@ -1873,6 +1940,7 @@ void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vo
#if HID_DFU_EN
, streaming chanend c_dfu_rx
#endif
, chanend c_mic_det
)
{
i2c_master_if i2c[1];
@@ -1885,6 +1953,7 @@ void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vo
#if HID_DFU_EN
, c_dfu_rx
#endif
, c_mic_det
);
}
}
@@ -1894,7 +1963,7 @@ void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vo
/* Configures the external audio hardware at startup */
void AudioHwInit()
{
p_ctl_mute <: 0;
// p_ctl_mute <: 0;
int result=0;
sw_pll_fixed_clock(MCLK_48);
@@ -1908,8 +1977,14 @@ void AudioHwInit()
/* Configures the external audio hardware for the required sample frequency */
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
{
#if UAC1_MODE == 1
static unsigned count = 1;
#else
static unsigned count = 0;
#endif
// p_ctl_mute <: 0;
g_samfreq = samFreq;
delay_milliseconds(2);
{
sw_pll_fixed_clock(mClk);
}
@@ -1919,7 +1994,7 @@ void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned s
if (count++ > 0)
{
p_ctl_mute <: 1;
// p_ctl_mute <: 1;
}
else
{
@@ -1928,3 +2003,74 @@ void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned s
unsafe {uc_audiohw :> dsdMode; }
}
void mute_handler(chanend c_mic_det)
{
// 开机mute sequence
p_ctl_mute <: 0;
delay_milliseconds(1000);
p_ctl_mute <: 0xf;
// mic detect: bit1=mic1 (插入=高, 拔出=低), bit2=mic2 (插入=低, 拔出=高)
unsigned det_val;
p_ctl_det :> det_val;
unsigned mic1_in = (det_val >> 1) & 1; // bit1: 1=inserted
unsigned mic2_in = ((det_val >> 2) & 1) ^ 1; // bit2: 0=inserted, invert
unsigned any_mic_in = mic1_in || mic2_in;
unsigned prev_any_mic_in = any_mic_in;
// 如果开机时全拔出发送mute
if (!any_mic_in) {
c_mic_det <: (unsigned)MIC_DET_MUTE;
}
timer tmr;
unsigned time;
tmr :> time;
#define MIC_DET_POLL_MS 10
time += MIC_DET_POLL_MS * 100000; // 10ms in 100MHz ticks
while (1) {
select {
case tmr when timerafter(time) :> void:
{
time += MIC_DET_POLL_MS * 100000;
p_ctl_det :> det_val;
mic1_in = (det_val >> 1) & 1;
mic2_in = ((det_val >> 2) & 1) ^ 1;
any_mic_in = mic1_in || mic2_in;
if (any_mic_in != prev_any_mic_in) {
// 状态变化立即mute防止pop音
c_mic_det <: (unsigned)MIC_DET_MUTE;
debug_printf("mic det change: mic1=%d mic2=%d -> mute\n", mic1_in, mic2_in);
// 等1s让插拔稳定
delay_milliseconds(1000);
// 重新读取稳定状态
p_ctl_det :> det_val;
mic1_in = (det_val >> 1) & 1;
mic2_in = ((det_val >> 2) & 1) ^ 1;
any_mic_in = mic1_in || mic2_in;
if (any_mic_in) {
// 有mic插入恢复音量
c_mic_det <: (unsigned)MIC_DET_UNMUTE;
debug_printf("mic stable inserted -> unmute\n");
}
// 全拔出则保持mute不发UNMUTE
prev_any_mic_in = any_mic_in;
// 重新同步timer
tmr :> time;
time += MIC_DET_POLL_MS * 100000;
}
break;
}
}
}
}

View File

@@ -15,8 +15,13 @@
#include "share_buffer.h"
void dnr_exchange_buffer(int32_t *data);
void buffer_exchange(chanend_t c_data, unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[]) {
extern uint32_t init_eq_data(unsigned sample_freq);
void dnr_exchange_buffer(int32_t *data);
// sample_freq 作为首字发送给 tile[0] 的 dsp_main用于采样率变化检测和 EQ 初始化
void buffer_exchange(chanend_t c_data, unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[], unsigned sample_freq) {
chan_out_word(c_data, sample_freq);
chan_out_buf_word (c_data, sampsFromUsbToAudio, 2);
chan_in_buf_word (c_data , sampsFromUsbToAudio, 2);
#if DNR_ENABLE == 1
@@ -29,12 +34,27 @@ void buffer_exchange(chanend_t c_data, unsigned sampsFromUsbToAudio[], unsigned
void dsp_main (chanend_t c_data) {
int play_input[NUM_USB_CHAN_OUT];
int play_output[I2S_CHANS_DAC];
int mic_input[NUM_USB_CHAN_IN];
int mic_input[I2S_CHANS_ADC];
int mic_output[I2S_CHANS_ADC];
int count = 0;
unsigned ch[1] = {2};
unsigned current_sample_freq = 0;
while (1) {
chan_in_buf_word (c_data , play_input, 2) ;
unsigned sample_freq = (unsigned)chan_in_word(c_data);
chan_in_buf_word (c_data , play_input, 2);
// 采样率变化:重新初始化 EQ 系数并清空 ring buffer避免残留状态污染
if (sample_freq != current_sample_freq && sample_freq != 0) {
current_sample_freq = sample_freq;
init_eq_data(sample_freq);
clear_ring_buffer(0);
clear_ring_buffer(1);
clear_ring_buffer(2);
clear_ring_buffer(3);
play_output[0] = 0;
play_output[1] = 0;
}
chan_out_buf_word (c_data , play_output, I2S_CHANS_DAC);
#if DNR_ENABLE == 1
chan_in_buf_word (c_data , mic_input, 2) ;
@@ -49,6 +69,5 @@ void dsp_main (chanend_t c_data) {
mic_output[0] = mic_input[0];
mic_output[1] = mic_input[1];
#endif
// dnr_exchange_buffer((int32_t *)mic_input, (int32_t *)mic_output);
}
}
}

View File

@@ -39,6 +39,7 @@ int32_t sys_vol = 0;
unsigned g_mic_vol_cmd_pending = 0;
chanend_t uc_ex3d_to_ubm, uc_eq_data;
static unsigned ubm_sample_freq = 0;
#if (STEREO_8K == 1) || (STEREO_2K == 1)
#define UBM_TO_EX3D_CHANS (2)
@@ -113,7 +114,7 @@ void key_sender(chanend_t c)
void UserBufferManagementInit(unsigned sampFreq)
{
(void)sampFreq;
ubm_sample_freq = sampFreq;
#if USE_EX3D == 1
memset(ubm_ingress, 0, sizeof(ubm_ingress));
memset(ubm_egress, 0, sizeof(ubm_egress));
@@ -131,7 +132,7 @@ void UserBufferManagementInit(unsigned sampFreq)
}
float fLevel[NUM_USB_CHAN_OUT] = {0,};
enum {UBM_A3D_OFF=0, UBM_A3D_VON=1, UBM_A3D_ON=2};
extern void buffer_exchange(chanend_t c_data, unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[]);
extern void buffer_exchange(chanend_t c_data, unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[], unsigned sample_freq);
extern unsigned int is_eq_disabled(void);
extern unsigned int g_eq_enable;
void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[])
@@ -139,6 +140,9 @@ void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudi
uint32_t is_3d;
uint32_t is_dnr;
uint32_t is_mute;
#if UAC1_MODE
return;
#endif
#if USE_EX3D == 1
#if defined(SPATIAL_DRAMA) || defined(SPATIAL_GAME) || defined(SPATIAL_MOVIE) || defined(SPATIAL_MUSIC)
@@ -234,8 +238,10 @@ void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudi
chan_in_buf_word(uc_ex3d_to_ubm, (uint32_t *)ubm_ingress, EX3D_TO_UBM_CHANS * DSP_BLOCK_LENGTH);
};
#endif
#if DNR_ENABLE == 1
buffer_exchange(uc_eq_data, sampsFromUsbToAudio, sampsFromAudioToUsb);
#if EQ_EN == 1 && USE_EX3D == 0
buffer_exchange(uc_eq_data, sampsFromUsbToAudio, sampsFromAudioToUsb, ubm_sample_freq);
#elif DNR_ENABLE == 1
buffer_exchange(uc_eq_data, sampsFromUsbToAudio, sampsFromAudioToUsb, ubm_sample_freq);
#endif
}

View File

@@ -34,6 +34,7 @@ extern unsigned int g_saved_eq_mode; // 改动原因:添加保存模式外部
extern void debug_print_eq_params(unsigned sample_freq);
extern uint32_t get_reference_time(void);
extern void update_eq_post_gain(void);
extern unsigned int g_eq_sample_rate;
extern unsigned g_windows_detect_done;
#pragma unsafe arrays
@@ -45,7 +46,7 @@ void dsp_core0(void)
static unsigned int usb_to_dsp_ratio = 1;
static int buffer_in_active = 0;
static int buffer_out_active = 0;
static unsigned int sample_freq = 48000;
static unsigned int sample_freq = 48000 ;
unsigned b_fade_in = 0;
unsigned u_in_step;
unsigned b_fade_out = 0;
@@ -138,7 +139,8 @@ void dsp_core0(void)
}
else
{
sample_freq = 48000;
GET_SHARED_GLOBAL(sample_freq, g_eq_sample_rate);
if (sample_freq == 0) sample_freq = 48000;
audio_in_samples[0] = read_from_ring_buffer(0);
audio_in_samples[1] = read_from_ring_buffer(1);

View File

@@ -32,6 +32,13 @@
| 0xA4 | SET_SOUND_EFFECT_MODE | 设置音效模式 | 主机→设备 | 设置音效模式0=无音效1=音乐模式2=游戏模式3=AI7.1模式) |
| 0xA5 | GET_SOUND_EFFECT_MODE | 获取音效模式 | 主机→设备 | 读取当前音效模式0-3 |
| 0xA6 | GET_FIRMWARE_VERSION | 获取固件版本 | 主机→设备 | 读取设备固件版本号BCD格式主版本.次版本.修订版本) |
| 0xA7 | FIRMWARE_UPGRADE_START | 开始固件升级 | 主机→设备 |
| 0xA8 | FIRMWARE_UPGRADE_DATA | 传输固件数据块固定57字节 | 主机→设备 |
| 0xA9 | FIRMWARE_UPGRADE_END | 结束固件升级,验证镜像 | 主机→设备 |
| 0xAA | FIRMWARE_UPGRADE_STATUS | 获取升级状态和进度 | 主机→设备 |
| 0xAB | FIRMWARE_UPGRADE_ABORT | 中止固件升级 | 主机→设备 |
| 0xAC | FIRMWARE_UPGRADE_ERASE | 擦除现有升级镜像 | 主机→设备 |
| 0xAE | DEVICE_REBOOT | 设备重启(通用命令) | 主机→设备 |
| 0xB0 | SET_EX3D_CMD | 发送EX3D命令 | 主机→设备 | 发送EX3D设置命令封装所有EX3D SET命令 |
| 0xB1 | GET_EX3D_CMD | 读取EX3D命令 | 主机→设备 | 读取EX3D参数封装所有EX3D GET命令 |
@@ -928,16 +935,6 @@
### 8.1 固件升级命令列表
| 指令码 | 命令名称 | 功能 | 方向 |
|--------|----------|------|------|
| 0xA7 | FIRMWARE_UPGRADE_START | 开始固件升级 | 主机→设备 |
| 0xA8 | FIRMWARE_UPGRADE_DATA | 传输固件数据块固定57字节 | 主机→设备 |
| 0xA9 | FIRMWARE_UPGRADE_END | 结束固件升级,验证镜像 | 主机→设备 |
| 0xAA | FIRMWARE_UPGRADE_STATUS | 获取升级状态和进度 | 主机→设备 |
| 0xAB | FIRMWARE_UPGRADE_ABORT | 中止固件升级 | 主机→设备 |
| 0xAC | FIRMWARE_UPGRADE_ERASE | 擦除现有升级镜像 | 主机→设备 |
| 0xAE | DEVICE_REBOOT | 设备重启(通用命令) | 主机→设备 |
### 8.2 0xA7 - FIRMWARE_UPGRADE_START
**请求**:

View File

@@ -18,7 +18,7 @@ static rtos_qspi_flash_t qspi_flash_ctx_s;
#define SECTOR_SIZE 4096
rtos_qspi_flash_t *qspi_flash_ctx = &qspi_flash_ctx_s;
__attribute__((fptrgroup(" local_block_device_read_fptr_grp")))
__attribute__((fptrgroup("local_block_device_read_fptr_grp")))
int local_block_device_read(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size)
{
@@ -27,7 +27,7 @@ int local_block_device_read(const struct lfs_config *c, lfs_block_t block,
return 0;
}
__attribute__((fptrgroup(" local_block_device_prog_fptr_grp")))
__attribute__((fptrgroup("local_block_device_prog_fptr_grp")))
int local_block_device_prog(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size)
{
@@ -36,7 +36,7 @@ int local_block_device_prog(const struct lfs_config *c, lfs_block_t block,
return 0;
}
__attribute__((fptrgroup(" local_block_device_erase_fptr_grp")))
__attribute__((fptrgroup("local_block_device_erase_fptr_grp")))
int local_block_device_erase(const struct lfs_config *c, lfs_block_t block)
{
unsigned address = (FS_BASE_ADDR + block * SECTOR_SIZE);
@@ -44,7 +44,7 @@ int local_block_device_erase(const struct lfs_config *c, lfs_block_t block)
return 0;
}
__attribute__((fptrgroup(" local_block_device_sync_fptr_grp")))
__attribute__((fptrgroup("local_block_device_sync_fptr_grp")))
int local_block_device_sync(const struct lfs_config *c)
{
return 0;
@@ -102,7 +102,8 @@ void lfs_deinit(void) {
swlock_release(&lfs_lock);
}
#pragma stackfunction 1300
#pragma stackfunction 1500
void lfs_read_config(unsigned char * config, unsigned char * buffer, unsigned size)
{
swlock_acquire(&lfs_lock);
@@ -119,7 +120,7 @@ void lfs_read_config(unsigned char * config, unsigned char * buffer, unsigned si
debug_printf("lfs_read_config: %s, result: %d\n", config, result);
if (result < 0) {
debug_printf("lfs_read_config: %s, read file failed, error: %d\n", config, result);
// Update: Added lfs_file_close to ensure file is closed even on error.
// Update: Added lfs_file_close to ensure file is closed even on error.
// Missing this caused subsequent open calls to assert/crash.
lfs_file_close(&lfs, &file);
swlock_release(&lfs_lock);
@@ -130,7 +131,7 @@ void lfs_read_config(unsigned char * config, unsigned char * buffer, unsigned si
}
#pragma stackfunction 1300
#pragma stackfunction 1500
void lfs_write_config(unsigned char * config, unsigned char * buffer, unsigned size)
{
swlock_acquire(&lfs_lock);
@@ -156,6 +157,7 @@ void lfs_write_config(unsigned char * config, unsigned char * buffer, unsigned s
// 检查文件是否存在
#pragma stackfunction 1200
int lfs_file_exists(const char * file_path)
{
swlock_acquire(&lfs_lock);
@@ -171,6 +173,7 @@ int lfs_file_exists(const char * file_path)
}
// EQ参数专用读写函数
#pragma stackfunction 1200
void lfs_read_eq_config(const char * file_path, unsigned char * buffer, unsigned size)
{
lfs_file_open(&lfs, &file, file_path, LFS_O_RDONLY);
@@ -178,6 +181,7 @@ void lfs_read_eq_config(const char * file_path, unsigned char * buffer, unsigned
lfs_file_close(&lfs, &file);
}
#pragma stackfunction 1500
void lfs_write_eq_config(const char * file_path, unsigned char * buffer, unsigned size)
{
lfs_file_open(&lfs, &file, file_path, LFS_O_RDWR | LFS_O_CREAT);
@@ -188,17 +192,19 @@ void lfs_write_eq_config(const char * file_path, unsigned char * buffer, unsigne
// 删除文件
#pragma stackfunction 1500
int lfs_remove_file(const char * file_path)
{
return lfs_remove(&lfs, file_path);
}
// 创建目录(通过创建临时文件然后删除)
#pragma stackfunction 1500
int lfs_create_directory(const char * dir_path)
{
char temp_file[256];
snprintf(temp_file, sizeof(temp_file), "%s/.dir", dir_path);
lfs_file_t file;
int result = lfs_file_open(&lfs, &file, temp_file, LFS_O_RDWR | LFS_O_CREAT);
if (result == 0) {

View File

@@ -432,9 +432,9 @@ extern int dsp_worker_tile(chanend c_dsp_to_ex3d, int worker_id);
extern void ex3d_task();
extern void hid_button_task(chanend cc_mic_level, chanend c_hid, chanend c_hidSendData, chanend c_uac_vol, chanend c_ex3d_hid_cmd);
#if HID_DFU_EN
extern void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, chanend c_audiohw_rx, streaming chanend c_dfu_rx);
extern void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, chanend c_audiohw_rx, streaming chanend c_dfu_rx, chanend c_mic_det);
#else
extern void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, chanend c_audiohw_rx);
extern void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, chanend c_audiohw_rx, chanend c_mic_det);
#endif
extern void dnr_dsp_proc_task(void);
@@ -447,6 +447,7 @@ extern unsafe streaming chanend uc_dfu;
#endif
extern void key_sender(chanend c_key);
extern void key_receiver(chanend c_key);
extern void mute_handler(chanend c_mic_det);
/* Main for USB Audio Applications */
@@ -550,6 +551,7 @@ int main()
chan c_eq_data;
chan c_uac_vol;
chan c_ex3d_hid_cmd;
chan c_mic_det;
par
{
@@ -558,6 +560,9 @@ int main()
par {
unsafe {
uc_audiohw = (chanend)c_audiohw;
#if EQ_EN == 1 && USE_EX3D == 0
SetEqDataChan(c_eq_data);
#endif
hid_button_task(cc_mic_level, c_hidRcvData, c_hidSendData, c_uac_vol, c_ex3d_hid_cmd);
}
#if USE_EX3D == 1
@@ -575,6 +580,7 @@ int main()
}
}
on tile[1]: mute_handler(c_mic_det);
on tile[0] : {
par {
@@ -586,6 +592,7 @@ int main()
#if HID_DFU_EN
, c_dfu
#endif
, c_mic_det
);
}
}

View File

@@ -4,6 +4,7 @@
#include <quadflashlib.h>
#include <xcore/chanend.h>
#include <xcore/channel.h>
#include "hmac.h"
#include "xua_conf.h"
#define WRITE_ENABLE_COMMAND (0x06)
@@ -31,7 +32,7 @@
#define PRSCUR_COMMAND (0x42)
#define ERSCUR_COMMAND (0x44)
#define RDSCUR_COMMAND (0x48)
#define HMAC_LEN 60
#define KEY_BLOCK_LEN 100
#define HMAC_GEN_LEN 20
@@ -40,19 +41,17 @@ extern unsigned short XUA_Endpoint0_getVendorId();
unsigned char hid_reply[64] = {0};
#if 0
void printArrayHex1(uint8_t array[], int size, int elementsPerLine) {
for (int i = 0; i < size; i++) {
printf("0x%x, ", array[i]);
debug_printf("0x%x ", array[i]);
// 在达到每行元素个数时换行
if ((i + 1) % elementsPerLine == 0) {
printf("\n");
debug_printf("\n");
}
}
printf("\n");
debug_printf("\n");
}
#endif
#define settw(a,b) {__asm__ __volatile__("settw res[%0], %1": : "r" (a) , "r" (b));}
#define setc(a,b) {__asm__ __volatile__("setc res[%0], %1": : "r" (a) , "r" (b));}
@@ -79,7 +78,7 @@ typedef struct {
clock qspiClkblk;
} fl_QSPIPorts;
*/
fl_QSPIPorts p_opt_qflash_tile0 =
fl_QSPIPorts p_opt_tile0 =
{
XS1_PORT_1B,
XS1_PORT_1C,
@@ -87,7 +86,7 @@ fl_QSPIPorts p_opt_qflash_tile0 =
XS1_CLKBLK_3
};
fl_QSPIPorts p_opt_qflash_tile1 =
fl_QSPIPorts p_opt_tile1 =
{
XS1_PORT_1F,
XS1_PORT_1G,
@@ -125,10 +124,12 @@ int flash_opt_enable_ports(fl_QSPIPorts *p_qflash)
if (!result)
{
/* All okay.. */
debug_printf("flash_opt_enable_ports success\n");
return 1;
}
else
{
debug_printf("flash_opt_enable_ports failed\n");
return 0;
}
}
@@ -143,15 +144,6 @@ void flash_cmd_opt(unsigned int cmd,
unsigned char input[], unsigned int num_in,
unsigned char output[], unsigned int num_out)
{
debug_printf("flash_cmd_opt: cmd = %02x, num_in = %d, num_out = %d\n", cmd, num_in, num_out);
for (size_t i = 0; i < num_in; i++)
{
debug_printf("input[%d] = %02x\n", i, input[i]);
}
for (size_t i = 0; i < num_out; i++)
{
debug_printf("output[%d] = %02x\n", i, output[i]);
}
fl_command(cmd,input,num_in,output, num_out);
}
@@ -182,7 +174,7 @@ void flash_opt_unlock(void)
uint8_t did[3];
/* Reason: 使用 tile0 端口连接 Flash保持原有逻辑 */
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0) {
if (flash_opt_enable_ports(&p_opt_tile0) == 0) {
debug_printf("flash_opt_unlock failed\n");
return;
}
@@ -293,8 +285,6 @@ unsigned compare_buff_diff(const uint8_t* actual, const uint8_t* expected, unsig
}
extern void hmac_sha1(const unsigned char *, unsigned long, const unsigned char * , unsigned long, unsigned char * );
void cal_hmac(uint8_t uid[], uint8_t did[], uint8_t hmac_bin[])
{
{
@@ -317,49 +307,64 @@ void cal_hmac(uint8_t uid[], uint8_t did[], uint8_t hmac_bin[])
hmac_sha1(key_bin, HMAC_GEN_LEN, msg_bin, HMAC_GEN_LEN, hmac_bin);
#if 0
printf("hmac_bin: \n");
printArrayHex1(hmac_bin, HMAC_LEN, 20);
#endif
}
}
uint8_t key_verify_old(unsigned sec_write, uint8_t expected_bin[], unsigned offset)
uint8_t opt_key_read(uint8_t key[], unsigned offset)
{
uint8_t read_bin[HMAC_LEN + 1];
uint8_t comp_bin[HMAC_LEN + 1];
uint8_t read_bin[KEY_BLOCK_LEN + 1];
uint8_t ret = 0;
if (flash_opt_enable_ports(&p_opt_tile0) == 0)
{
return 0;
}
flash_opt_read(read_bin, KEY_BLOCK_LEN + 1);
for (int i = 0; i < 20; i++)
{
key[i] = read_bin[i + offset * 20 + 1];
}
flash_opt_disable_ports();
return 1;
}
uint8_t key_verify_program(unsigned verify_write, uint8_t expected_bin[], unsigned offset)
{
uint8_t read_bin[KEY_BLOCK_LEN + 1];
uint8_t comp_bin[KEY_BLOCK_LEN + 1];
uint8_t uid[20];
uint8_t did[4];
uint8_t ret = 0;
uint8_t hmac_bin[20];
flash_opt_read(read_bin, HMAC_LEN + 1);
flash_opt_read(read_bin, KEY_BLOCK_LEN + 1);
flash_opt_read_uid(uid, 20);
flash_opt_read_did(did, 3);
cal_hmac(uid, did, hmac_bin);
if (sec_write)
if (verify_write)
{
if (offset == 0)
if (offset == 1)
{
for (int i = 0; i < 20; i++)
cal_hmac(uid, did, hmac_bin);
if (compare_buff_diff(hmac_bin, expected_bin, 20) == 0)
{
read_bin[i + 1] = expected_bin[i];
}
}
else if (offset == 1)
{
for (int i = 0; i < 20; i++)
{
read_bin[i + 21] = expected_bin[i];
return 0;
}
}
flash_opt_write2(&read_bin[1], HMAC_LEN);
for (int i = 0; i < 20; i++)
{
read_bin[i + offset * 20 + 1] = expected_bin[i];
}
flash_opt_write2(&read_bin[1], KEY_BLOCK_LEN);
delay_milliseconds(10);
flash_opt_read(comp_bin, HMAC_LEN + 1);
if (compare_buff_diff(&comp_bin[1], &read_bin[1], HMAC_LEN) == 1)
flash_opt_read(comp_bin, KEY_BLOCK_LEN + 1);
if (compare_buff_diff(&comp_bin[1], &read_bin[1], KEY_BLOCK_LEN) == 1)
{
debug_printf("compare OK\n");
ret = 1;
@@ -367,50 +372,18 @@ uint8_t key_verify_old(unsigned sec_write, uint8_t expected_bin[], unsigned offs
}
else
{
if (offset == 0)
flash_opt_read(read_bin, KEY_BLOCK_LEN + 1);
if (compare_buff_diff(expected_bin, &read_bin[offset * 20 + 1], 20) == 1)
{
flash_opt_read(read_bin, HMAC_LEN + 1);
if (compare_buff_diff(hmac_bin, &read_bin[1], 20) == 1)
{
debug_printf("key_verified\n");
ret = 1;
}
}
else if (offset == 1)
{
flash_opt_read(read_bin, HMAC_LEN + 1);
if (compare_buff_diff(hmac_bin, &read_bin[21], 20) == 1)
{
debug_printf("key_verified\n");
ret = 1;
}
debug_printf("key_verified\n");
ret = 1;
}
}
return ret;
}
void flash_read_uid(uint8_t *uid)
{
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
{
return;
}
flash_opt_read_uid(uid, 20);
flash_opt_disable_ports();
}
void flash_read_did(uint8_t *did)
{
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
{
return;
}
flash_opt_read_did(did, 3);
flash_opt_disable_ports();
}
void get_key_ret(uint8_t *buffer)
{
//printf("get_key_ret2\n");
@@ -423,35 +396,6 @@ void get_key_ret(uint8_t *buffer)
//printArrayHex1(buffer, 20, 20);
}
unsigned char g_hid_pass_data[64];
extern void hidSetChangePending(unsigned int);
void user_read_hidpass(unsigned char * hidPassData)
{
int i = 0;
for (i = 0; i < 64; i++)
{
hidPassData[i] = g_hid_pass_data[i];
debug_printf("hidPassData[%d] = %02x\n", i, hidPassData[i]);
g_hid_pass_data[i] = 0;
}
}
void user_set_hidpass(unsigned char *data)
{
#if HID_CONTROLS
for (int i = 0; i < 63; i++)
{
g_hid_pass_data[i] = data[i];
debug_printf("g_hid_pass_data[%d] = %02x\n", i, g_hid_pass_data[i]);
}
hidSetChangePending(0x1);
#endif
}
static chanend_t g_flash_opt_c;
void flash_opt_set_chan(chanend_t c) {
@@ -466,72 +410,49 @@ void flash_opt_exchange_buffer(uint8_t in[64], uint8_t out[64]) {
chan_in_buf_byte(g_flash_opt_c, out, 40);
}
void flash_opt_key(chanend_t c) {
uint8_t buffer[64], reply[40] = {0, 0, 0, 0};
uint32_t ret;
delay_milliseconds(2);
while (1) {
chan_in_buf_byte(c, buffer, 40);
if (flash_opt_enable_ports(&p_opt_qflash_tile1) == 0) {
reply[0] = 0;
}
else
{
switch (buffer[3])
{
case 9:
flash_opt_read_did(&reply[1], 3);
reply[0] = 0x55;
break;
case 10:
flash_opt_read_uid(&reply[1], 21);
reply[0] = 0x55;
break;
case 8:
ret = key_verify_old(1, &buffer[4], 0);
if (ret == 1)
{
debug_printf("write key ret 0x55\n");
reply[0] = 0x55;
}
else
{
reply[0] = 0;
}
break;
}
flash_opt_disable_ports();
chan_out_buf_byte(c, reply, 40) ;
}
}
}
uint8_t key_validate(void)
uint8_t key_validate(uint8_t offset)
{
uint8_t ret = 0;
uint8_t data[1] = {0};
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
uint8_t read_bin[KEY_BLOCK_LEN + 1];
uint8_t uid[20];
uint8_t did[4];
uint8_t hmac_bin[20];
if (flash_opt_enable_ports(&p_opt_tile0) == 0)
{
return 0;
}
ret = key_verify_old(0, data, 0);
if (ret == 1)
flash_opt_read(read_bin, KEY_BLOCK_LEN + 1);
flash_opt_read_uid(uid, 20);
flash_opt_read_did(did, 3);
cal_hmac(uid, did, hmac_bin);
if (compare_buff_diff(hmac_bin, &read_bin[offset * 20 + 1], 20) == 1)
{
SetKeyFlag(0x20241224);
debug_printf("key_verified\n");
ret = 1;
}
ret = key_verify_old(0, data, 1);
if (ret == 1)
{
SetKeyFlag(0x20241224);
}
flash_opt_disable_ports();
return ret;
}
void read_uid_did(uint8_t uid[])
{
if (flash_opt_enable_ports(&p_opt_tile0) == 0)
{
return;
}
flash_opt_read_uid(uid, 20);
flash_opt_read_did(uid, 3);
flash_opt_disable_ports();
}
void program_key(uint8_t *buffer, int datalength)
{
if (buffer[0] == 0x77 && buffer[1] == 0x5B)
@@ -541,14 +462,13 @@ void program_key(uint8_t *buffer, int datalength)
{
case 1:
debug_printf("verify key\n");
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
if (flash_opt_enable_ports(&p_opt_tile0) == 0)
{
hid_reply[0] = 0;
}
else
{
uint8_t data[1] = {0};
ret = key_verify_old(0, data, 0);
ret = key_verify_program(0, &buffer[3], 1);
if (ret == 1)
{
hid_reply[0] = 0x55;
@@ -562,13 +482,13 @@ void program_key(uint8_t *buffer, int datalength)
break;
case 2:
debug_printf("write key\n");
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
if (flash_opt_enable_ports(&p_opt_tile0) == 0)
{
hid_reply[0] = 0;
}
else
{
ret = key_verify_old(1, &buffer[3], 0);
ret = key_verify_program(1, &buffer[3], 1);
debug_printf("write key ret %d\n", ret);
if (ret == 1)
@@ -584,7 +504,7 @@ void program_key(uint8_t *buffer, int datalength)
break;
case 3:
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
if (flash_opt_enable_ports(&p_opt_tile0) == 0)
{
hid_reply[0] = 0;
}
@@ -597,7 +517,7 @@ void program_key(uint8_t *buffer, int datalength)
}
break;
case 4:
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
if (flash_opt_enable_ports(&p_opt_tile0) == 0)
{
hid_reply[0] = 0;
}
@@ -610,7 +530,7 @@ void program_key(uint8_t *buffer, int datalength)
}
break;
case 5:
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
if (flash_opt_enable_ports(&p_opt_tile0) == 0)
{
hid_reply[0] = 0;
}
@@ -623,6 +543,7 @@ void program_key(uint8_t *buffer, int datalength)
}
break;
case 6:
#if XUA_USB_EN == 1
debug_printf("get pid vid\n");
unsigned short pid = XUA_Endpoint0_getProductId();
unsigned short vid = XUA_Endpoint0_getVendorId();
@@ -631,22 +552,118 @@ void program_key(uint8_t *buffer, int datalength)
hid_reply[4] = (vid >> 8) & 0xff;
hid_reply[3] = vid & 0xff;
hid_reply[0] = 0x55;
#endif
break;
case 7:
debug_printf("write aizip key\n");
if (flash_opt_enable_ports(&p_opt_tile0) == 0)
{
hid_reply[0] = 0;
}
else
{
uint8_t ret = key_verify_program(1, &buffer[3], 0);
debug_printf("write key ret %d\n", ret);
if (ret == 1)
{
hid_reply[0] = 0x55;
}
else
{
hid_reply[0] = 0;
}
flash_opt_disable_ports();
}
break;
case 12:
debug_printf("verify aizip key\n");
if (flash_opt_enable_ports(&p_opt_tile0) == 0)
{
hid_reply[0] = 0;
}
else
{
ret = key_verify_program(0, &buffer[3], 0);
if (ret == 1)
{
hid_reply[0] = 0x55;
}
else
{
hid_reply[0] = 0;
}
flash_opt_disable_ports();
}
break;
case 13:
case 15:
case 17:
case 19:
case 21:
case 23:
case 25:
case 27:
case 29:
case 31:
case 33:
debug_printf("write key offset %d\n", ((buffer[2] - 13) / 2) + 2);
if (flash_opt_enable_ports(&p_opt_tile0) == 0)
{
hid_reply[0] = 0;
}
else
{
uint8_t ret = key_verify_program(1, &buffer[3], ((buffer[2] - 13) / 2) + 2);
debug_printf("write key ret %d\n", ret);
if (ret == 1)
{
hid_reply[0] = 0x55;
}
else
{
hid_reply[0] = 0;
}
flash_opt_disable_ports();
}
break;
case 14:
case 16:
case 18:
case 20:
case 22:
case 24:
case 26:
case 28:
case 30:
case 32:
case 34:
debug_printf("verify key offset %d\n", ((buffer[2] - 14) / 2) + 2);
if (flash_opt_enable_ports(&p_opt_tile0) == 0)
{
hid_reply[0] = 0;
}
else
{
ret = key_verify_program(0, &buffer[3], ((buffer[2] - 14) / 2) + 2);
if (ret == 1)
{
hid_reply[0] = 0x55;
}
else
{
hid_reply[0] = 0;
}
flash_opt_disable_ports();
}
break;
case 8:
case 9:
case 10:
//flash_opt_exchange_buffer(buffer, hid_reply);
// debug_printf("write aizip key tile 0 %02x\n", hid_reply[0]);
for (int i = 0; i < datalength; i++)
hid_reply[i] = 0;
case 11:
break;
}
}
else
{
//xmos_printf(&buffer[1], datalength - 1);
}
}

View File

@@ -11,6 +11,8 @@
| 0x82 | SET_MIC_VOLUME | 设置麦克风增益级别 | 主机→设备 | 设置麦克风PGA增益0=静音, 1-37=0dB~36dB, 1dB/步) |
| 0x83 | GET_MIC_VOLUME | 获取麦克风增益级别 | 主机→设备 | 读取当前麦克风PGA增益级别0=静音, 1-37=0dB~36dB |
| 0x84 | FACTORY_RESET | 恢复出厂默认设置 | 主机→设备 | 删除Flash中所有已保存参数设备重启后自动恢复出厂默认值 |
| 0x85 | SET_AI_NOISE_STRENGTH | 设置AI降噪强度 | 主机→设备 | 设置AI降噪强度0=关闭2-100偶数=强度级别步进2100对应最强-200dB |
| 0x86 | GET_AI_NOISE_STRENGTH | 获取AI降噪强度 | 主机→设备 | 读取当前AI降噪强度强度变化含按键切换、开机初始值时设备主动上报 |
| 0x87 | SET_MONITOR_SWITCH | 设置耳返开关 | 主机→设备 | 设置耳返ADC→耳机监听开关0=关闭1=开启保存到Flash |
| 0x88 | GET_MONITOR_SWITCH | 获取耳返开关状态 | 主机→设备 | 读取当前耳返开关状态0=关闭1=开启) |
| 0x8A | SET_EQ_MODE | 切换EQ模式 | 主机→设备 | 切换EQ模式 |
@@ -149,7 +151,66 @@
- 重启后所有参数将恢复为出厂默认值
- 此操作不可撤销
### 2.0d 0x87 - SET_MONITOR_SWITCH (设置耳返开关)
### 2.0d 0x85 - SET_AI_NOISE_STRENGTH (设置AI降噪强度)
**功能**: 设置AI降噪强度级别
**方向**: 主机→设备
**数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x77 | 同步头1
1 | 1 | 0x85 | 命令码
2 | 1 | uint8 | 强度值 (0=关闭, 2/4/.../100=强度级别, 步进2)
3-62 | 60 | 0x00 | 保留字节
```
**参数说明**:
- **强度值范围**: 0、2、4、6、…、100共51个有效值
- **0**: 关闭AI降噪
- **2-100步进2**: 开启AI降噪强度递增内部dB映射`dB = -(strength × 2)`
- 2 → -4 dB最轻微降噪
- 50 → -100 dB
- 100 → -200 dB最强降噪出厂默认
- **奇数或 >100** 为无效值,固件将拒绝(返回无响应)
**设备端处理**:
- 强度=0关闭AI降噪算法熄灭LED_ANCflag_aidenoise_onoff=0
- 强度=2-100开启AI降噪算法点亮LED_ANCflag_aidenoise_onoff=1更新内部降噪深度
- 设置成功后设备主动上报当前强度0x86格式
- **不保存到Flash**重启后AI降噪恢复为开启强度=100即-200dB最强
**返回值**:
无直接返回设置成功后设备通过0x86格式主动上报当前强度值。
### 2.0e 0x86 - GET_AI_NOISE_STRENGTH (获取AI降噪强度)
**功能**: 读取设备当前AI降噪强度强度变化时设备主动上报
**方向**: 主机→设备(请求),设备→主机(响应/主动上报)
**请求数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x77 | 同步头1
1 | 1 | 0x86 | 命令码
2-62 | 61 | 0x00 | 保留字节
```
**响应数据包格式**(含主动上报):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1 | 1 | 0x77 | 同步头1
2 | 1 | 0x86 | 同步头2
3 | 1 | uint8 | 当前强度值 (0=关闭, 2-100=强度级别)
4-62 | 59 | 0x00 | 保留字节
```
**主动上报说明**:
- **开机时**:设备初始化完成后主动上报当前强度(出厂默认=100
- **按键切换**用户按下AI降噪按键时设备主动上报新强度关闭时上报0开启时上报恢复的强度
- **HID SET_AI_NOISE_STRENGTH0x85命令成功执行后**,设备主动上报新强度
### 2.0f 0x87 - SET_MONITOR_SWITCH (设置耳返开关)
**功能**: 设置耳返ADC→耳机监听开关控制是否将麦克风输入实时路由到耳机输出
**方向**: 主机→设备
**数据包格式**:
@@ -172,6 +233,7 @@
- 若麦克风当前处于静音状态则无论耳返开关为何值reg 0x0035保持0x0000
- 保存到Flash`monitor_sw`路径),断电重启后自动恢复
- 设置成功后用0x88格式响应当前状态
- 出厂默认关闭0
**返回值**:
设置成功后设备回复0x88格式响应。
@@ -187,7 +249,7 @@
4-62 | 59 | 0x00 | 保留字节
```
### 2.0e 0x88 - GET_MONITOR_SWITCH (获取耳返开关状态)
### 2.0g 0x88 - GET_MONITOR_SWITCH (获取耳返开关状态)
**功能**: 读取当前耳返开关状态
**方向**: 主机→设备(请求),设备→主机(响应)
**请求数据包格式**:
@@ -674,7 +736,7 @@
---------|------|------|------
0 | 1 | 0x77 | 同步头1
1 | 1 | 0xB0 | 命令码
2-5 | 4 | uint32 | EX3D命令码包含SET标志
2-5 | 4 | uint32 | EX3D命令码包含SET标志,参考下方两个命令详情
6-9 | 4 | uint32 | 参数1根据EX3D命令不同而不同
10-13 | 4 | uint32 | 参数2根据EX3D命令不同而不同
14-17 | 4 | uint32 | 参数3根据EX3D命令不同而不同
@@ -682,26 +744,11 @@
```
**EX3D命令码说明**:
- 基础命令码范围: 0x80-0x94
- SET命令格式: `基础命令码 & ~0x0100`清除第9位
- 支持的SET命令
- 0x81: CMD_OPEN打开EX3D
- 0x82: CMD_ONOFF设置EX3D开关
- 0x83: CMD_ANGLE设置角度
- 0x84: CMD_SOUND_FIELD设置声场模式
- 0x85: CMD_MUTE设置静音
- 0x86: CMD_ON_GAIN设置开启增益
- 0x87: CMD_LMT_THRESHOLD设置限制器阈值
- 0x88: CMD_UPMIX设置上混
- 0x89: CMD_LFE设置LFE增益
- 0x8A: CMD_OFF_GAIN设置关闭增益
- 0x8E: CMD_LMT_ATTACKK_TIME设置限制器攻击时间
- 0x8F: CMD_LMT_RELEASE_TIME设置限制器释放时间
- 0x90: CMD_TEST_CANCEL取消测试
- 0x91: CMD_TEST_STEP测试步骤
- 0x92: CMD_TEST_ROTATE测试旋转
- 0x93: CMD_EXPAND_GAIN设置扩展增益
- 0x94: CMD_REDUCE_GAIN设置减少增益
- 0x87: CMD_LMT_THRESHOLD设置枪声阈值
- 0x93: CMD_EXPAND_GAIN设置脚步声增益
**设备端处理**:
- 解析EX3D命令码提取基础命令码和参数
@@ -729,32 +776,17 @@
---------|------|------|------
0 | 1 | 0x77 | 同步头1
1 | 1 | 0xB1 | 命令码
2-5 | 4 | uint32 | EX3D命令码包含GET标志
2-5 | 4 | uint32 | EX3D命令码包含GET标志,参考下方两个命令详情
6-9 | 4 | uint32 | 参数1根据EX3D命令不同而不同如通道号、索引等
10-62 | 53 | 0x00 | 保留字节或扩展参数
```
**EX3D命令码说明**:
- 基础命令码范围: 0x80-0x94
- GET命令格式: `基础命令码 | 0x0100`设置第9位
- 支持的GET命令
- 0x180: CMD_CH_NUM获取通道数量
- 0x182: CMD_ONOFF获取EX3D开关
- 0x183: CMD_ANGLE获取角度
- 0x184: CMD_SOUND_FIELD获取声场模式
- 0x185: CMD_MUTE获取静音
- 0x186: CMD_ON_GAIN获取开启增益
- 0x187: CMD_LMT_THRESHOLD获取限制器阈值
- 0x188: CMD_UPMIX获取上混
- 0x189: CMD_LFE获取LFE增益
- 0x18A: CMD_OFF_GAIN获取关闭增益
- 0x18B: CMD_SOUND_FIELD_NUM获取声场模式数量
- 0x18C: CMD_SOUND_FIELD_NAME获取声场模式名称
- 0x18D: CMD_LEVEL获取电平
- 0x18E: CMD_LMT_ATTACKK_TIME获取限制器攻击时间
- 0x18F: CMD_LMT_RELEASE_TIME获取限制器释放时间
- 0x193: CMD_EXPAND_GAIN获取扩展增益
- 0x194: CMD_REDUCE_GAIN获取减少增益
- 0x187: CMD_LMT_THRESHOLD获取枪声阈值
- 0x193: CMD_EXPAND_GAIN获取脚步声增益
**设备端处理**:
- 解析EX3D命令码提取基础命令码和参数
@@ -780,7 +812,7 @@
- 单值命令返回1个uint32值
- 多值命令如角度、多通道数据返回多个uint32值
- 字符串命令(如声场名称):先返回长度(uint32),然后返回字符串数据
- 详细的返回值格式请参考ex3d_protocol.md文档
- 详细的返回值格式请参考下方两个命令详情
**使用说明**:
- 该命令用于统一封装所有EX3D读取命令