add initial code

Signed-off-by: Andy Liu <jie.liu@telink-semi.com>
This commit is contained in:
Andy Liu
2022-05-23 11:51:25 +08:00
parent aa9177c907
commit f0e01bc8c7
333 changed files with 64364 additions and 0 deletions
Executable
+22
View File
@@ -0,0 +1,22 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if (ohos_kernel_type == "liteos_m") {
import("//kernel/liteos_m/liteos.gni")
module_name = get_path_info(rebase_path("."), "name")
module_group(module_name) {
modules = [ "b91" ]
}
}
+16
View File
@@ -0,0 +1,16 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
rsource "*/Kconfig.liteos_m.defconfig.series"
+16
View File
@@ -0,0 +1,16 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
rsource "*/Kconfig.liteos_m.series"
+24
View File
@@ -0,0 +1,24 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
config SOC_COMPANY_TELINK
bool
if SOC_COMPANY_TELINK
config SOC_COMPANY
default "telink"
rsource "*/Kconfig.liteos_m.soc"
endif # SOC_COMPANY_TELINK
Executable
+52
View File
@@ -0,0 +1,52 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/lite/config/component/lite_component.gni")
import("//build/lite/config/subsystem/lite_subsystem.gni")
import("//kernel/liteos_m/liteos.gni")
import("//drivers/adapter/khdf/liteos_m/hdf.gni")
driver_sdk_path = "b91m_ble_sdk"
config("B91_config") {
defines = [
"__PROJECT_B91_EXTERNAL=1"
]
include_dirs = [
"liteos_m/inc",
"$driver_sdk_path",
"$driver_sdk_path/common",
"$driver_sdk_path/drivers",
"$driver_sdk_path/drivers/B91",
"$driver_sdk_path/vendor/common",
]
configs = [
"//drivers/adapter/khdf/liteos_m:hdf_config",
]
}
module_name = get_path_info(rebase_path("."), "name")
module_group(module_name) {
deps = [
driver_sdk_path,
"hdf",
]
modules = [
"liteos_m",
]
}
+19
View File
@@ -0,0 +1,19 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
config SOC
string
default "B91"
depends on SOC_B91
+25
View File
@@ -0,0 +1,25 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if SOC_SERIES_B91
rsource "Kconfig.liteos_m.defconfig.b91"
config SOC_SERIES
string
default "B91"
endif
+23
View File
@@ -0,0 +1,23 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
config SOC_SERIES_B91
bool "Telink B91 Series"
select RISC-V
select SOC_COMPANY_TELINK
select CPU_RISCV32
help
Enable support for telink b91 series
+23
View File
@@ -0,0 +1,23 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
choice
prompt "Telink B91 Series SoC"
depends on SOC_SERIES_B91
config SOC_B91
bool "SoC B91"
endchoice
+27
View File
@@ -0,0 +1,27 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/lite/config/component/lite_component.gni")
static_library("hal_file_static") {
sources = [ "src/hal_file.c" ]
include_dirs = [
"//utils/native/lite/hals/file",
"//utils/native/lite/include",
]
deps = []
}
+253
View File
@@ -0,0 +1,253 @@
/******************************************************************************
* Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "utils_file.h"
#include "hal_file.h"
#define RD_WR_FIELD_MASK 0x000f
#define CREAT_EXCL_FIELD_MASK 0x00f0
#define TRUNC_FILED_MASK 0x0f00
#define ADDITIONAL_LEN 2
#define MAX_PATH_LEN 40
#define MAX_OPEN_FILE_NUM 32
#define ROOT_PATH "/data"
#define DIR_SEPARATOR "/"
#define SLOT_AVAILABLE -1
#define HAL_ERROR -1
static int FileHandlerArray[MAX_OPEN_FILE_NUM] =
{
SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE,
SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE,
SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE,
SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE,
};
static int GetAvailableFileHandlerIndex(void)
{
int i = MAX_OPEN_FILE_NUM;
for (; i > 0; i--) {
if (FileHandlerArray[i - 1] == SLOT_AVAILABLE)
break;
}
return i;
}
static int ConvertFlags(int oflag)
{
int ret = 0;
int buffer = 0;
buffer = (oflag & RD_WR_FIELD_MASK);
if (buffer == O_RDONLY_FS) {
ret = O_RDONLY;
} else if (buffer == O_WRONLY_FS) {
ret = O_WRONLY;
} else if (buffer == O_RDWR_FS) {
ret = O_RDWR;
}
buffer = (oflag & CREAT_EXCL_FIELD_MASK);
if ((buffer & O_CREAT_FS) != 0) {
ret |= O_CREAT;
}
if ((buffer & O_EXCL_FS) != 0) {
ret |= O_EXCL;
}
buffer = (oflag & TRUNC_FILED_MASK);
if ((buffer & O_TRUNC_FS) != 0) {
ret |= O_TRUNC;
}
if ((buffer & O_APPEND_FS) != 0) {
ret |= O_APPEND;
}
return ret;
}
static char *GetActualFilePath(const char *path)
{
int len;
char *file_path = NULL;
len = strnlen(path, MAX_PATH_LEN);
if (len >= MAX_PATH_LEN) {
printf("path is too long!\r\n");
return NULL;
}
len += (strlen(ROOT_PATH) + ADDITIONAL_LEN);
file_path = (char *)malloc(len);
if (file_path == NULL) {
printf("malloc failed!\r\n");
return NULL;
}
strcpy(file_path, ROOT_PATH);
strcat(file_path, DIR_SEPARATOR);
strcat(file_path, path);
}
int HalFileOpen(const char *path, int oflag, int mode)
{
int index;
int fd;
char *file_path;
index = GetAvailableFileHandlerIndex();
if (index == 0) {
printf("no space available!\r\n");
return HAL_ERROR;
}
file_path = GetActualFilePath(path);
if (file_path == NULL) {
return HAL_ERROR;
}
fd = open(file_path, ConvertFlags(oflag));
if (fd < 0) {
printf("failed to open file '%s': %d\r\n", file_path, errno);
free(file_path);
return HAL_ERROR;
}
FileHandlerArray[index - 1] = fd;
free(file_path);
return index;
}
int HalFileClose(int fd)
{
int ret;
/* make sure fd is within the allowed range, which is 1 to MAX_OPEN_FILE_NUM */
if ((fd > MAX_OPEN_FILE_NUM) || (fd <= 0)) {
return HAL_ERROR;
}
ret = close(FileHandlerArray[fd - 1]);
if (ret != 0) {
return HAL_ERROR;
}
FileHandlerArray[fd - 1] = SLOT_AVAILABLE;
return ret;
}
int HalFileRead(int fd, char *buf, unsigned int len)
{
/* make sure fd is within the allowed range, which is 1 to MAX_OPEN_FILE_NUM */
if ((fd > MAX_OPEN_FILE_NUM) || (fd <= 0)) {
return HAL_ERROR;
}
return read(FileHandlerArray[fd - 1], buf, len);
}
int HalFileWrite(int fd, const char *buf, unsigned int len)
{
/* make sure fd is within the allowed range, which is 1 to MAX_OPEN_FILE_NUM */
if ((fd > MAX_OPEN_FILE_NUM) || (fd <= 0)) {
return HAL_ERROR;
}
return write(FileHandlerArray[fd - 1], buf, len);
}
int HalFileDelete(const char *path)
{
char *file_path;
int ret;
file_path = GetActualFilePath(path);
if (file_path == NULL) {
return HAL_ERROR;
}
ret = unlink(file_path);
free(file_path);
return ret;
}
int HalFileStat(const char *path, unsigned int *fileSize)
{
char *file_path;
struct stat f_info;
int ret;
file_path = GetActualFilePath(path);
if (file_path == NULL) {
return HAL_ERROR;
}
ret = stat(file_path, &f_info);
*fileSize = f_info.st_size;
free(file_path);
return ret;
}
int HalFileSeek(int fd, int offset, unsigned int whence)
{
int ret = 0;
struct stat f_info;
/* make sure fd is within the allowed range, which is 1 to MAX_OPEN_FILE_NUM */
if ((fd > MAX_OPEN_FILE_NUM) || (fd <= 0)) {
return HAL_ERROR;
}
ret = fstat(FileHandlerArray[fd - 1], &f_info);
if (ret != 0) {
return HAL_ERROR;
}
if (whence == SEEK_SET_FS) {
if (offset > f_info.st_size) {
ret = HAL_ERROR;
}
}
ret = lseek(FileHandlerArray[fd - 1], offset, whence);
if ((ret > f_info.st_size) || (ret < 0)) {
return HAL_ERROR;
}
return ret;
}
+1242
View File
File diff suppressed because it is too large Load Diff
+82
View File
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>B91_ble_multi_conn_sdk</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
<dictionary>
<key>?name?</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.append_environment</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildArguments</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildCommand</key>
<value>make</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildLocation</key>
<value>${workspace_loc:/Eagle_Driver_Demo}/9518_UART_DEMO</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
<value>clean</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.contents</key>
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
<value>false</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.stopOnError</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
<value>false</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>
+44
View File
@@ -0,0 +1,44 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/lite/config/component/lite_component.gni")
import("//build/lite/config/subsystem/lite_subsystem.gni")
static_library("b91m_ble_sdk") {
sources = [
"common/utility.c",
"drivers/B91/aes.c",
"drivers/B91/analog.c",
"drivers/B91/clock.c",
"drivers/B91/stimer.c",
"drivers/B91/gpio.c",
"drivers/B91/uart.c",
"drivers/B91/flash.c",
"drivers/B91/ext_driver/software_pa.c",
]
sources += [
"application/keyboard/keyboard.c",
"vendor/common/simple_sdp.c",
"vendor/common/blt_common.c",
"vendor/common/custom_pair.c",
"vendor/common/device_manage.c",
]
libs = ["proj_lib/liblt_9518.a"]
configs += ["..:B91_config"]
}
+154
View File
@@ -0,0 +1,154 @@
/********************************************************************************************************
* @file aes_ccm.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include "stack/ble/ble_format.h"
#define AES_BLOCK_SIZE 16
//#define SUCCESS 0
enum {
AES_SUCC = SUCCESS,
AES_NO_BUF,
AES_FAIL,
};
typedef struct {
u32 pkt;
u8 dir;
u8 iv[8];
} ble_cyrpt_nonce_t;
typedef struct {
u64 enc_pno;
u64 dec_pno;
u8 sk[16]; //session key
ble_cyrpt_nonce_t nonce;
u8 st;
u8 enable; //1: slave enable; 2: master enable
u8 mic_fail;
} ble_crypt_para_t;
struct CCM_FLAGS_TAG {
union {
struct {
u8 L : 3;
u8 M : 3;
u8 aData :1;
u8 reserved :1;
} bf;
u8 val;
};
};
typedef struct CCM_FLAGS_TAG ccm_flags_t;
typedef struct {
union {
u8 A[AES_BLOCK_SIZE];
u8 B[AES_BLOCK_SIZE];
} bf;
u8 tmpResult[AES_BLOCK_SIZE];
u8 newAstr[AES_BLOCK_SIZE];
} aes_enc_t;
enum{
CRYPT_NONCE_TYPE_ACL = 0,
CRYPT_NONCE_TYPE_CIS = 1,
CRYPT_NONCE_TYPE_BIS = 2,
};
/**
* @brief this function is used to encrypt the plaintext
* @param[in] *key - aes key: 128 bit key for the encryption of the data, little--endian.
* @param[in] *plaintext - 128 bit data block that is requested to be encrypted, little--endian.
* @param[out] *result - 128 bit encrypted data block, little--endian.
* @return none.
* @Note Input data requires strict Word alignment
*/
void aes_ll_encryption(u8* key, u8* plaintext, u8 *encrypted_data);
/**
* @brief this function is used to initialize the aes_ccm initial value
* @param[in] ltk - encryption key, LTK
* @param[in] skdm -
* @param[in] skds -
* @param[in] ivm -
* @param[in] ivs -
* @param[in] pd - Reference structure ble_crypt_para_t
* @return none
*/
void aes_ll_ccm_encryption_init (u8 *ltk, u8 *skdm, u8 *skds, u8 *ivm, u8 *ivs, ble_crypt_para_t *pd);
/**
* @brief this function is used to encrypt the aes_ccm value
* @param[in] pkt - plaint_text
* @param[in] master - ll_ccm_enc: Master role must use 1, Slave role must use 0;
ll_ccm_dec: Master role must use 0, Slave role must use 1;
* @param[in] pd - Reference structure ble_crypt_para_t
* @return none
*/
//void aes_ll_ccm_encryption(u8 *pkt, int master, ble_crypt_para_t *pd);
/**
* @brief this function is used to encrypt the aes_ccm value, version2
* @param[in] pd - Reference structure leCryptCtrl_t
* @return none
*/
void aes_ll_ccm_encryption(llPhysChnPdu_t *pllPhysChnPdu, u8 role, u8 ll_type, ble_crypt_para_t *pd);
/**
* @brief this function is used to decrypt the aes_ccm value
* @param[in] pkt - plaint_text
* @param[in] master - ll_ccm_enc: Master role must use 1, Slave role must use 0;
ll_ccm_dec: Master role must use 0, Slave role must use 1;
* @param[in] pd - Reference structure ble_crypt_para_t
* @return 0: decryption succeeded; 1: decryption failed
*/
//int aes_ll_ccm_decryption(u8 *pkt, int master, ble_crypt_para_t *pd);
/**
* @brief this function is used to decrypt the aes_ccm value, version2
* @param[in] pd - Reference structure leCryptCtrl_t
* @return 0: decryption succeeded; 1: decryption failed
*/
int aes_ll_ccm_decryption(llPhysChnPdu_t *pllPhysChnPdu, u8 role, u8 ll_type, ble_crypt_para_t *pd);
+37
View File
@@ -0,0 +1,37 @@
/********************************************************************************************************
* @file algorithm.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2021.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#ifndef ALGORITHM_H_
#define ALGORITHM_H_
#include "algorithm/aes_ccm/aes_ccm.h"
#include "algorithm/crypto/crypto_alg.h"
#include "algorithm/ecc/ecc_ll.h"
#include "algorithm/ecc/hw_ecc.h"
#include "algorithm/lc3/inc/lc3_enc.h"
#include "algorithm/lc3/inc/lc3_dec.h"
#endif /* ALGORITHM_H_ */
+166
View File
@@ -0,0 +1,166 @@
/********************************************************************************************************
* @file crypto_alg.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#ifndef CRYPTO_ALG_H_
#define CRYPTO_ALG_H_
/*
* @brief This function is used to generate the prand
* @param[out] prand - The out are stored in little endian format
* @return none
* */
void blt_crypto_alg_prand(unsigned char prand[3]);
/*
* @brief Resolvable Private Address Generation and Resolution
* @param[in] irk - The IRKs are stored in little endian format
* @param[in] r - The r are stored in little endian format
* @param[out] out - The out are stored in little endian format
* @return none
* */
void blt_crypto_alg_ah(const unsigned char irk[16], unsigned char r[3], unsigned char out[3]);
/**
* @brief This function is used to generate the confirm values
* @param[out] c1: the confirm value, little--endian.
* @param[in] key: aes key, little--endian.
* @param[in] r: the plaintext, little--endian.
* @param[in] pres: packet buffer2, little--endian.
* @param[in] preq: packet buffer2, little--endian.
* @param[in] iat: initiate address type
* @param[in] ia: initiate address, little--endian.
* @param[in] rat: response address type
* @param[in] ra: response address, little--endian.
* @return none.
* @Note Input data requires strict Word alignment
*/
void blt_crypto_alg_c1(unsigned char *c1, unsigned char key[16], unsigned char r[16], unsigned char pres[7], unsigned char preq[7], unsigned char iat, unsigned char ia[6], unsigned char rat, unsigned char ra[6]);
/**
* @brief This function is used to generate the STK during the LE legacy pairing process.
* @param[out] *STK - the result of encrypt, little--endian.
* @param[in] *key - aes key, little--endian.
* @param[in] *r1 - the plaintext1, little--endian.
* @param[in] *r2 - the plaintext2, little--endian.
* @return none.
* @Note Input data requires strict Word alignment
*/
void blt_crypto_alg_s1(unsigned char *stk, unsigned char key[16], unsigned char r1[16], unsigned char r2[16]);
/**
* @brief This function is used to compute confirm value by function f4
* --- Ca: f4(U, V, X, Z) = AES-CMACX (U || V || Z) ---
* @param[out] r: the output of the confirm:128-bits, big--endian.
* @param[in] u: is the 256-bits, big--endian.
* @param[in] v: is the 256-bits, big--endian.
* @param[in] x: is the 128-bits, big--endian.
* @param[in] z: is the 8-bits
* @return none.
*/
void blt_crypto_alg_f4 (unsigned char *r, unsigned char u[32], unsigned char v[32], unsigned char x[16], unsigned char z);
/**
* @brief This function is used to generate the numeric comparison values during authentication
* stage 1 of the LE Secure Connections pairing process by function g2
* @param[in] u: is the 256-bits, big--endian.
* @param[in] v: is the 256-bits, big--endian.
* @param[in] x: is the 128-bits, big--endian.
* @param[in] y: is the 128-bits, big--endian.
* @return pincode value: 32-bits.
*/
unsigned int blt_crypto_alg_g2 (unsigned char u[32], unsigned char v[32], unsigned char x[16], unsigned char y[16]);
/**
* @brief This function is used to generate derived keying material in order to create the LTK
* and keys for the commitment function f6 by function f5
* @param[out] mac: the output of the MAC value:128-bits, big--endian.
* @param[out] ltk: the output of the LTK value:128-bits, big--endian.
* @param[in] w: is the 256-bits, big--endian.
* @param[in] n1: is the 128-bits, big--endian.
* @param[in] n2: is the 128-bits, big--endian.
* @param[in] a1: is the 56-bits, big--endian.
* @param[in] a2: is the 56-bits, big--endian.
* @return none.
*/
void blt_crypto_alg_f5 (unsigned char *mac, unsigned char *ltk, unsigned char w[32], unsigned char n1[16], unsigned char n2[16],
unsigned char a1[7], unsigned char a2[7]);
/**
* @brief This function is used to generate check values during authentication stage 2 of the
* LE Secure Connections pairing process by function f6
* @param[out] *e: the output of Ea or Eb:128-bits, big--endian.
* @param[in] w: is the 256-bits, big--endian.
* @param[in] n1: is the 128-bits, big--endian.
* @param[in] n2: is the 128-bits, big--endian.
* @param[in] a1: is the 56-bits, big--endian.
* @param[in] a2: is the 56-bits, big--endian.
* @return none.
*/
void blt_crypto_alg_f6 (unsigned char *e, unsigned char w[16], unsigned char n1[16], unsigned char n2[16],
unsigned char r[16], unsigned char iocap[3], unsigned char a1[7], unsigned char a2[7]);
/**
* @brief This function is used to convert keys of a given size from one key type to another
* key type with equivalent strength
* @param[out] r: the output of h6:128-bits, big--endian.
* @param[in] w: is the 128-bits, big--endian.
* @param[in] keyid: is the 32-bits, big--endian.
* @return none.
*/
void blt_crypto_alg_h6 (unsigned char *r, unsigned char w[16], unsigned char keyid[4]);
/**
* @brief This function is used to convert keys of a given size from one key type to another
* key type with equivalent strength
* --- h7(SALT, W) = AES-CMACsalt(W) ---
* @param[out] r: the output of h7:128-bits, big--endian.
* @param[in] salt: is the 128-bits, big--endian.
* @param[in] w: is the 128-bits, big--endian.
* @return none.
*/
void blt_crypto_alg_h7 (unsigned char *r, unsigned char salt[16], unsigned char w[16]);
/**
* @brief This function is used to generate the Group Session Key (GSK) for encrypting or
* decrypting payloads of an encrypted BIS.
* --- h8(K, S, keyID) = AES-CMACik(keyID) ---
* @param[out] r: the output of h8:128-bits, big--endian.
* @param[in] k: is the 128-bits, big--endian.
* @param[in] s: is the 128-bits, big--endian.
* @param[in] keyid: is the 32-bits, big--endian.
* @return none.
*/
void blt_crypto_alg_h8 (unsigned char *r, unsigned char k[16], unsigned char s[16], unsigned char keyId[4]);
#endif /* CRYPTO_ALG_H_ */
+8
View File
@@ -0,0 +1,8 @@
__build__/
__pycache__
*.pyc
*.pyo
*.pyd
*.pyz
*.egg-info/
.DS_Store
+40
View File
@@ -0,0 +1,40 @@
/********************************************************************************************************
* @file ecc_ll.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#ifndef ECC_CURVE_H_
#define ECC_CURVE_H_
/* Curve selection options */
typedef enum{
// ECC_use_secp160r1,
ECC_use_secp192r1,
ECC_use_secp224r1,
ECC_use_secp256r1,
// ECC_use_secp256k1,
}ecc_curve_t;
#endif /* ECC_CURVE_H_ */
+69
View File
@@ -0,0 +1,69 @@
/********************************************************************************************************
* @file ecc_ll.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#ifndef ECC_LL_H_
#define ECC_LL_H_
#include "algorithm/ecc/ecc_curve.h"
extern const u8 blt_ecc_dbg_priv_key192[24];
extern const u8 blt_ecc_dbg_pub_key192[48];
extern const u8 blt_ecc_dbg_priv_key256[32];
extern const u8 blt_ecc_dbg_pub_key256[64];
/**
* @brief This function is used to register the random number function needed for ECC calculation
* @param none
* @return none
*/
void blt_ecc_init(void);
/**
* @brief This function is used to generate an ECDH public-private key pairs
* @param[out] pub[64]: output ecdh public key
* @param[out] priv[64]: output ecdh private key
* @param[in] use_dbg_key: 0: Non-debug key , others: debug key
* @return 1: success
* 0: failure
*/
int blt_ecc_gen_key_pair(unsigned char *pub, unsigned char *priv, ecc_curve_t curve, bool use_dbg_key);
/**
* @brief This function is used to calculate DHKEY based on the peer public key and own private key
* @param[in] peer_pub_key[64]: peer public key
* @param[in] own_priv_key[32]: own private key
* @param[out] out_dhkey[32]: dhkey key
* @return 1: success
* 0: failure
*/
int blt_ecc_gen_dhkey(const unsigned char *peer_pub, const unsigned char *own_priv, unsigned char *out_dhkey, ecc_curve_t curve);
#endif /* ECC_LL_H_ */
+77
View File
@@ -0,0 +1,77 @@
/********************************************************************************************************
* @file hw_ecc.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#ifndef HW_ECC_H_
#define HW_ECC_H_
#include "algorithm/ecc/hw_ecc.h"
#include "algorithm/ecc/ecc_curve.h"
#if ( (MCU_CORE_TYPE == MCU_CORE_827x) || (MCU_CORE_TYPE == MCU_CORE_9518) )
/* hECC_RNG_Function type
The RNG function should fill 'size' random bytes into 'dest'. It should return 1 if
'dest' was filled with random data, or 0 if the random data could not be generated.
The filled-in values should be either truly random, or from a cryptographically-secure PRNG.
A correctly functioning RNG function must be set (using hECC_set_rng()) before calling
hECC_make_key(). */
typedef int (*hECC_rng_func)(unsigned char *dest, unsigned size);
/**
* @brief The function that will be used to generate random bytes.
* @param[in] resister predefined TRNG function
* @return none
*/
void hwECC_set_rng(hECC_rng_func rng_func);
/**
* @brief get ECCP key pair(the key pair could be used in ECDH).
* @param[out] public_key - public key, big--endian.
* @param[out] private_key - private key, big--endian.
* @param[in] curve_sel - ecc_curve select, e.g.: p-256r1.
* @return 1(success), 0(error).
*/
unsigned char hwECC_make_key(unsigned char *public_key, unsigned char *private_key, ecc_curve_t curve_sel);
/**
* @brief ECDH compute key.
* @param[in] local_prikey - local private key, big--endian.
* @param[in] public_key - peer public key, big--endian.
* @param[out] dhkey - output dhkey, big--endian.
* @param[in] curve_sel - ecc_curve select, e.g.: p-256r1.
* @Return 1(success); 0(error).
*/
unsigned char hwECC_shared_secret(const unsigned char *public_key, const unsigned char *private_key,
unsigned char *secret, ecc_curve_t curve_sel);
#endif /* HW_ECC_H_ */
#endif /* The end of #if((MCU_CORE_TYPE == MCU_CORE_827x) || (MCU_CORE_TYPE == MCU_CORE_9518)) */
+33
View File
@@ -0,0 +1,33 @@
#ifndef _CONFIG_H
#define _CONFIG_H
#if (LE_AUDIO_ENABLE)
#define ALG_LC3_ENABLE 1
#define ANDES_INTRINSIC
#endif
#if (ALG_LC3_ENABLE)
#define FIXED_POINT 32
#define DISABLE_LTPF 0
//#define LC3_16K_ONLY
//#define DUMP_IMTERMEDIATE
//#define USE_SPREAD_FFT
//#define ANDES_PROFILE
//#define ANDES_INTRINSIC
//#define EN_SPEC_INTERMEDIATE
#ifdef ANDES_INTRINSIC
#undef DUMP_IMTERMEDIATE
#define ANDES_DSPLIB_MAX
#define ANDES_DSPLIB_DPROD
#endif
#define Errata_ID_15041
//#define KNOWN_ISSUE
//#define KNOWN_ISSUE_NC
//#define OLD_HEADER
#endif
#endif // !CONFIG_H
+55
View File
@@ -0,0 +1,55 @@
#ifndef _LC3_COMMON_H
#define _LC3_COMMON_H
#include "config.h"
#if (ALG_LC3_ENABLE)
#define LC3_MODE_10MS (0)
#define LC3_MODE_75MS (1)
#define LC3_MAX_CHANNELS (2)
#define LC3_MAX_SAMPLES (480)
#define LC3_MAX_FRAME_SIZE (870)
#ifdef LC3_16K_ONLY
#define LC3_MAX_NF (160)
#define LC3_MAX_NE (160)
#else
#define LC3_MAX_NF (480)
#define LC3_MAX_NE (400)
#endif
#if LC3_MAX_NF==480
#define LC3_MAX_INPUT_DELAY 60
#elif LC3_MAX_NF==320
#define LC3_MAX_INPUT_DELAY 40
#elif LC3_MAX_NF==240
#define LC3_MAX_INPUT_DELAY 30
#elif LC3_MAX_NF==160
#define LC3_MAX_INPUT_DELAY 20
#else
#define LC3_MAX_INPUT_DELAY 10
#endif // LC3_MAX_NF==480
#define L_NUM_MAX (11)
#define L_DEN_MAX (13)
#define P_INT_MAX (228)
#define LTPF_MEM_MAX (P_INT_MAX * LC3_MAX_NF / 128 + (L_DEN_MAX + 1) / 2)
typedef enum {
LC3_PARA_FRAMESIZE = 0,
LC3_PARA_OUTSIZE,
LC3_PARA_CHANNELS,
LC3_PARA_SAMPLERATE,
LC3_PARA_BITRATE,
LC3_PARA_SAMPLES,
LC3_PARA_DELAY,
LC3_PARA_END
} LC3_PARAMETER;
#endif
#endif
+107
View File
@@ -0,0 +1,107 @@
#ifndef _LC3_DEC_H
#define _LC3_DEC_H
#include "lc3_types.h"
#include "lc3_common.h"
#include "config.h"
#if (ALG_LC3_ENABLE)
#include "../src/fft_lib/_kiss_fft_guts.h" // FIXME
#include "../src/fft_lib/kiss_fft_custom/kiss_fft_custom.h"
/*! LC3 decoder error codes. */
typedef enum
{
LC3DEC_OK = 0,
LC3DEC_ERROR_GETPARA = 1,
LC3DEC_ERROR_INIT,
LC3DEC_ERROR_SHAPE,
LC3DEC_ERROR_SETPARA,
LC3DEC_ERROR_BITSTREAM,
LC3DEC_ERROR_ARITHMATIC,
} LC3DEC_Error;
typedef struct LC3_DEC
{
Word32 nSamplerate;
Word32 nBitrate;
Word32 nChannels;
Word16 NF;
Word16 NE;
Word16 Nb;
Word16 Nms; // 20 ->10ms,15->7.5ms
Word16 Nms_mode; // 0->10ms,1->7.5ms
Word16 Z;
/* Bandwidth detector */
Word16 nBitsBw;
Word16 nFsIdx;
/* side infor */
Word16 nPbw;
Word16 lastnz;
Word16 lsbMode;
Word16 gg_ind; // used in global_gain
Word16 num_tns_filters; // used in tns decoder
Word16 rc_order[2]; // tns
Word16 rc_i[8][2]; // tns
Word16 ind_LF; // sns
Word16 ind_HF; // sns
Word16 shape_j; // sns
Word16 gain_i; // sns
Word32 idxA; // sns
Word32 idxB; // sns
Word16 LS_indA; // sns
Word16 LS_indB; // sns
Word16 pitch_present; // ltpf
Word16 ltpf_active; // ltpf
Word16 pitch_index; // ltpf
Word16 p_int; // ltpf
Word16 p_fr; // ltpf
Word16 mem_ltpf_active; // ltpf
Word16 mem_p_int; // ltpf
Word16 mem_p_fr; // ltpf
Word16 F_NF;
/* bitstream pointer */
Word16 bp_side;
Word16 mask_side;
/* noise filling */
Word16 zeroFrameFlag;
Word32 nf_seed;
/* imdct */
// kiss_fft_cfg kiss_fft_state;
kiss_fft_state16_ptr kiss_fft_state;
Word16* mdct_twiddle;
Word16* mdct_sin_twiddle;
Word16 sin_step;
const Word16* W_MDCT;
Word16 W_size;
/* plc */
Word32 plc_seed;
#ifdef FIXED_POINT
Word32* mem_imdct;
Word32* mem_plc_buf;
Word32* mem_x;
Word32* mem_x_ltpf;
Word16* mem_c_num;
Word16* mem_c_den;
#else
double* mem_imdct;
double* mem_plc_buf;
double* mem_x;
double* mem_x_ltpf;
double* mem_c_num;
double* mem_c_den;
#endif
/* plc */
Word16 bec_detect;
} LC3_DEC_STRU;
LC3DEC_Error lc3dec_init(LC3_DEC_STRU* dec, Word32 samplerate, Word32 bitrate, Word16 channels, Word16 Nms_mode);
LC3DEC_Error lc3dec_decode_frame(LC3_DEC_STRU* dec, UWord8* inbuf, UWord32 inlen, Word16* outbuf);
LC3DEC_Error lc3dec_get_parameter(LC3_DEC_STRU* dec, LC3_PARAMETER para, Word32* val);
LC3DEC_Error lc3dec_set_parameter(LC3_DEC_STRU* dec, LC3_PARAMETER para, Word32* val);
LC3DEC_Error lc3dec_free(LC3_DEC_STRU* dec);
#endif
#endif
+141
View File
@@ -0,0 +1,141 @@
#ifndef _LC3_ENC_H
#define _LC3_ENC_H
#include "lc3_types.h"
#include "lc3_common.h"
#include "config.h"
#if (ALG_LC3_ENABLE)
#include "../src/fft_lib/_kiss_fft_guts.h"
#include "../src/fft_lib/kiss_fft_custom/kiss_fft_custom.h"
#ifdef ANDES_INTRINSIC
#include "nds_filtering_math.h"
#endif // DEBUG
//#define EN_SPEC_INTERMEDIATE
/*! LC3 encoder error codes. */
typedef enum
{
LC3ENC_OK = 0,
LC3ENC_ERROR_INIT = 1,
LC3ENC_ERROR_GETPARA,
LC3ENC_ERROR_SETPARA
} LC3ENC_Error;
typedef struct LC3_ENC
{
#ifndef FIXED_POINT
// Spectral quantization
double nbits_offset_old;
Word32 nbits_spec_old;
Word32 nbits_est_old;
Word32 reset_offset_old;
// LTPF
double stage1;
double stage2;
Word32 len_12k8;
Word32 D_LTPF;
double* x_12k8_HP_last; // input data of last frame
double* x_12k8_HP_D_last; //
double* x_i_fr_last;
double* x_6k4_last;
Word16 T_prev; // pirch_lag estimated in previous frame
Word16 mem_ltpf_active;
double mem_nc;
double mem_mem_nc;
Word16 mem_pitch;
// att
double A_att_last;
double E_att_last;
Word32 P_att_last;
double* x_att_last;
// BW
Word16 nbits_bw;
// mdct
double* W_MDCT;
Word16 W_size;
Word16 Nb; // number of bands
#else
/* mdct */
//kiss_fft_cfg kiss_fft_state;
kiss_fft_state16_ptr kiss_fft_state;
const Word16* mdct_twiddle;
const Word16* mdct_sin_twiddle;
Word16 sin_step;
const Word16* W_MDCT;
Word16 W_size;
Word16 Nb; // number of bands
/* bw detector */
Word16 nbits_bw;
/* attack detector */
Word16 M_F;
Word16 m_stop;
Word16 att_scaling;
Word16 x_att_last[2];
Word32 A_att_last;
Word32 E_att_last;
Word32 P_att_last;
/* tns */
Word32 nn_idx;
/* ltpf */
#if 0
nds_bq_df1_q15_t ltpf_highpass_q15;
#endif // ANDES_INTRINSIC
Word16 ltpf_enable;
Word32 len_12k8;
Word32 D_LTPF;
Word32 stage1;
Word32 stage2;
Word16 x_12k8_last[128]; // x_12k8 of last frame
Word16 x_12k8_D_buf[232+130]; //x_12k8_D_buf[232] is x_12k8_D[0]
Word16 x_12k8_D_last_exp;
Word16 x_12k8_D_last_3[3];
Word16 x_6k4_last[114+64];
Word16 x_6k4_last_exp;
Word32 T_prev; // pirch_lag estimated in previous frame
Word16 mem_ltpf_active;
Word16 mem_nc;
Word16 mem_mem_nc;
Word16 mem_pitch;
/* Spectral quantization */
Word32 nbits_offset_old;
Word16 nbits_spec_old;
Word16 nbits_est_old;
Word32 reset_offset_old;
Word16 gg_off;
Word16 nbits_ari;
#endif // !FIXED_POINT
/* overall */
Word32 frame_counter;
Word32 fs; // sample rate
Word16 fs_ind; // index of fs
Word16 channelNum; //channal number
Word32 bitrate; // bit rate
Word16 NF; // sample number of one frame
Word16 NE; // frequency number of one frame
Word16 Nms_mode;// 0->10ms,1->7.5ms
Word16 Nms; // 20 ->10ms,15->7.5ms
Word16 nbytes; // bytes of one frame
Word32 nbits; // bits of one frame
Word16 input_last[LC3_MAX_NF]; // input data of last frame
} LC3_ENC_STRU;
LC3ENC_Error lc3enc_init(LC3_ENC_STRU* enc, Word32 nSamplerate, Word16 nChannels, Word32 nBitrate,int nMs_mode);
LC3ENC_Error lc3enc_encode_frame(LC3_ENC_STRU* enc, Word16* input, UWord8* output);
LC3ENC_Error lc3enc_get_parameter(LC3_ENC_STRU* enc, LC3_PARAMETER para, Word32* val);
LC3ENC_Error lc3enc_set_parameter(LC3_ENC_STRU* enc, LC3_PARAMETER para, Word32* val);
LC3ENC_Error lc3enc_change_bitrate(LC3_ENC_STRU* enc, Word32 bitrate);
LC3ENC_Error lc3enc_free(LC3_ENC_STRU* enc);
#endif
#endif
+68
View File
@@ -0,0 +1,68 @@
#ifndef _LC3_TYPES_H
#define _LC3_TYPES_H
#include "config.h"
#ifndef ANDES_INTRINSIC
typedef char Word8;
typedef short Word16;
typedef int Word32;
typedef long long Word64;
typedef unsigned char UWord8;
typedef unsigned short UWord16;
typedef unsigned int UWord32;
#else
#include <nds_math_types.h>
typedef int8_t Word8;
typedef int16_t Word16;
typedef int32_t Word32;
typedef int64_t Word64;
typedef uint8_t UWord8;
typedef uint16_t UWord16;
typedef uint32_t UWord32;
#endif
typedef struct {
Word16 r;
Word16 i;
}lc3_cpx;
typedef struct {
Word32 r;
Word32 i;
}kiss_fft_cpx;
struct kiss_fft_state {
int nfft;
int inverse;
int factors[2 * 32]; // 32->MAXFACTORS
kiss_fft_cpx twiddles[1];
};
typedef struct kiss_fft_state* kiss_fft_cfg;
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX_32
#define MAX_32 (0x7fffffffL)
#endif // !MAX_32
#ifndef MIN_32
#define MIN_32 (0x80000000L)
#endif // !MIN_32
#ifndef MAX_16
#define MAX_16 (32767)
#endif
#ifndef MIN_16
#define MIN_16 (-32768)
#endif
#endif
+21
View File
@@ -0,0 +1,21 @@
#ifndef _ARITHMATIC_DECODER_H
#define _ARITHMATIC_DECODER_H
#include "../inc/lc3_dec.h"
#include "constant.h"
#if (ALG_LC3_ENABLE)
typedef struct {
Word32 low;
Word32 range;
} ST_STRU;
LC3DEC_Error dec_arithmatic(LC3_DEC_STRU* dec, UWord8* inbuf, UWord32 inlen,
Word16* X_q, Word16* resBits, Word16* pBitsResidual);
#endif //#if (ALG_LC3_ENABLE)
#endif
+223
View File
@@ -0,0 +1,223 @@
#ifndef BASIC_OP_H
#define BASIC_OP_H
#include "../inc/lc3_types.h"
#include "constant.h"
#if (ALG_LC3_ENABLE)
/* short logical shift */
//Word16 lshr(Word16 var1, Word16 var2);
/* int shift*/
//Word32 L_shl(Word32 L_var1, Word16 var2);
//Word32 L_shr(Word32 L_var1, Word16 var2);
/* short shift*/
Word16 shr(Word16 var1, Word16 var2);
Word16 shl(Word16 var1, Word16 var2);
/* short shift and rounding*/
Word16 shr_r(Word16 var1, Word16 var2);
/* if x==0 return 0 */
Word16 getScaleFactor16(Word16* x, Word16 len);
/* if x==0 return 16 */
Word16 getScaleFactor16_0(Word16* x, Word16 len);
Word16 getScaleWord32(Word32* x, Word16 len);
/* if x==0 return 32 */
Word16 getScaleFactor32_0(Word32* x, Word16 len);
Word32 Norm32Norm(const Word32* x, Word16 shift, const Word16 length, Word16* result_e);
/* log2 */
inline Word16 BASOP_Util_Log2_16(Word32 x, Word16 x_e)
{
Word16 shift, tmp1, tmp2;
Word16 outInt, outFrac, out;
if (x == 0)
{
return (MIN_16);
}
/* Scale Input */
shift = clrs32(x);
x = L_shl(x, (shift - 10));
/* Integer part */
outInt = ((x_e - shift - 1) << 9);
/* Fractional part */
tmp1 = mac_r(x, -33, 16384);
tmp2 = lshr((Word16)(x) , 6);
outFrac = mac_r(Log2_16_table1[tmp1], Log2_16_table2[tmp1], tmp2);
/* Output */
out = (outInt + outFrac);
return out;
}
inline Word32 BASOP_Util_Log2(Word32 x)
{
Word32 exp;
Word16 exp_e;
Word16 nIn;
Word16 accuSqr;
Word32 accuRes;
/* x never == 0
if (x == 0)
{
return ((Word32)MIN_32);
}
*/
/* normalize input, calculate integer part */
exp_e = clrs32(x);
x = L_shl(x, exp_e);
exp =(Word32) (exp_e);
/* calculate (1-normalized_input) */
nIn = ((MAX_32 - x))>>16;
/* approximate ln() for fractional part (nIn *c0 + nIn^2*c1 + nIn^3*c2 + ... + nIn^8 *c7) */
/* iteration 1, no need for accumulation */
accuRes = L_mult(nIn, ldCoeff[0]); /* nIn^i * coeff[0] */
accuSqr = mult_16(nIn, nIn); /* nIn^2, nIn^3 .... */
/* iteration 2 */
accuRes = L_mac(accuRes, accuSqr, ldCoeff[1]); /* nIn^i * coeff[1] */
accuSqr = mult_16(accuSqr, nIn); /* nIn^2, nIn^3 .... */
/* iteration 3 */
accuRes = L_mac(accuRes, accuSqr, ldCoeff[2]); /* nIn^i * coeff[2] */
accuSqr = mult_16(accuSqr, nIn); /* nIn^2, nIn^3 .... */
/* iteration 4 */
accuRes = L_mac(accuRes, accuSqr, ldCoeff[3]); /* nIn^i * coeff[3] */
accuSqr = mult_16(accuSqr, nIn); /* nIn^2, nIn^3 .... */
/* iteration 5 */
accuRes = L_mac(accuRes, accuSqr, ldCoeff[4]); /* nIn^i * coeff[4] */
accuSqr = mult_16(accuSqr, nIn); /* nIn^2, nIn^3 .... */
/* iteration 6 */
accuRes = L_mac(accuRes, accuSqr, ldCoeff[5]); /* nIn^i * coeff[5] */
accuSqr = mult_16(accuSqr, nIn); /* nIn^2, nIn^3 .... */
/* iteration 7, no need to calculate accuSqr any more */
accuRes = L_mac(accuRes, accuSqr, ldCoeff[6]); /* nIn^i * coeff[6] */
/* ld(fractional part) = ln(fractional part)/ln(2), 1/ln(2) = (1 + 0.44269504) */
accuRes = (L_shr(accuRes, 1) + mult_16_16_32( (accuRes)>>16, 14506));
accuRes = L_shr(accuRes, 6 - 1); /* fractional part/LD_DATA_SCALE =6 */
exp = L_shl(exp, (31 - 6)); /* integer part/LD_DATA_SCALE */
accuRes = (accuRes - exp); /* result = integer part + fractional part */
return (accuRes);
}
Word32 BASOP_Util_InvLog2(Word32 x);
Word16 Inv16(Word16 mantissa, Word16* exponent);
Word16 BASOP_Util_Divide3216_Scale(Word32 x,Word16 y,Word16* s);
Word16 BASOP_Util_Divide1616_Scale(Word16 x, Word16 y, Word16* s);
void Mpy_32_16_ss(Word32 L_var1, Word16 var2, Word32* L_varout_h, UWord16* varout_l);
Word32 Mpy_32_16(Word32 x, Word16 y);
Word16 div_s(Word16 var1, Word16 var2);
#ifdef USE_SPREAD_FFT
void Mpy_32_32_ss(Word32 L_var1, Word32 L_var2, Word32* L_varout_h, UWord32* L_varout_l);
Word32 Mpy_32_32(Word32 x, Word32 y);
#define SHC(x) ((Word16)x)
#define shr_pos shr
#define shl_pos shl
#define L_shr_pos L_shr
#define L_shl_pos L_shl
#define SCALEFACTORN2 (3)
#define SCALEFACTOR5 (4)
#define SCALEFACTOR6 (4)
#define SCALEFACTOR8 (4)
#define SCALEFACTOR10 (5)
#define SCALEFACTOR15 (5)
#define SCALEFACTOR30_1 (5)
#define SCALEFACTOR30_2 (1)
#define Mpy_32_xx mult_32_Q15_32
#define SCALEFACTOR20 (5)
#define WORD32_BITS 32
#define WORD16_BITS 16
#define WORD322WORD16(val) \
((((((val) >> (WORD32_BITS - WORD16_BITS - 1)) + 1) > (((long)1 << WORD16_BITS) - 1)) && ((long)(val) > 0)) \
? (Word16)(short)(((long)1 << (WORD16_BITS - 1)) - 1) \
: (Word16)(short)((((val) >> (WORD32_BITS - WORD16_BITS - 1)) + 1) >> 1))
#define FFTC(x) WORD322WORD16((Word32)x)
#define C31 (FFTC(0x91261468)) /* FL2WORD32( -0.86602540) -sqrt(3)/2 */
#define C31_32 0x91261468
#define C51 (FFTC(0x79bc3854)) /* FL2WORD32( 0.95105652) */
#define C52 (FFTC(0x9d839db0)) /* FL2WORD32(-1.53884180/2) */
#define C53 (FFTC(0xd18053ce)) /* FL2WORD32(-0.36327126) */
#define C54 (FFTC(0x478dde64)) /* FL2WORD32( 0.55901699) */
#define C55 (FFTC(0xb0000001)) /* FL2WORD32(-1.25/2) */
#define C81 (FFTC(0x5a82799a)) /* FL2WORD32( 7.071067811865475e-1) */
#define C82 (FFTC(0xa57d8666)) /* FL2WORD32(-7.071067811865475e-1) */
#define C51_32 (0x79bc3854) /* FL2WORD32( 0.95105652) */
#define C52_32 (0x9d839db0) /* FL2WORD32(-1.53884180/2) */
#define C53_32 (0xd18053ce) /* FL2WORD32(-0.36327126) */
#define C54_32 (0x478dde64) /* FL2WORD32( 0.55901699) */
#define C55_32 (0xb0000001) /* FL2WORD32(-1.25/2) */
#define C81_32 (0x5a82799a) /* FL2WORD32( 7.071067811865475e-1) */
#define C82_32 (0xa57d8666) /* FL2WORD32(-7.071067811865475e-1) */
#define cplxMpy4_8_0(re, im, a, b, c, d) \
do \
{ \
re = L_shr(L_sub(Mpy_32_xx(a, c), Mpy_32_xx(b, d)), 1); \
im = L_shr(L_add(Mpy_32_xx(a, d), Mpy_32_xx(b, c)), 1); \
} while (0)
#define cplxMpy4_8_1(re, im, a, b) \
do \
{ \
re = L_shr(a, 1); \
im = L_shr(b, 1); \
} while (0)
#define cplxMpy4_8_2(re, im, a, b, c, d) \
do \
{ \
re = L_shr(L_add(Mpy_32_32(a, c), Mpy_32_32(b, d)), 1); \
im = L_shr(L_sub(Mpy_32_32(b, c), Mpy_32_32(a, d)), 1); \
} while (0)
#define cplxMpy4_12_0(re, im, a, b, c, d) \
do \
{ \
re = L_sub(Mpy_32_xx(a, c), Mpy_32_xx(b, d)); \
im = L_add(Mpy_32_xx(a, d), Mpy_32_xx(b, c)); \
} while (0)
#define cplxMpy4_12_1(re, im, a, b) \
do \
{ \
re = a; \
im = b; \
} while (0)
#endif
#endif //#if (ALG_LC3_ENABLE)
#endif // !BASIC_OP_H
#pragma once
+12
View File
@@ -0,0 +1,12 @@
#ifndef _BITSTREAM_DECODER_H
#define _BITSTREAM_DECODER_H
#include "../inc/lc3_dec.h"
#if (ALG_LC3_ENABLE)
LC3DEC_Error dec_bitstream(LC3_DEC_STRU* dec, UWord8* inbuf, UWord32 inlen);
#endif
#endif
+44
View File
@@ -0,0 +1,44 @@
#ifndef _COMMON_FUNC_H
#define _COMMON_FUNC_H
#include "../inc/lc3_dec.h"
#if (ALG_LC3_ENABLE)
#ifdef ANDES_INTRINSIC
#include "nds_basic_math.h"
#include "nds_utils_math.h"
#include "nds_filtering_math.h"
#include "nds_statistics_math.h"
#endif
#ifdef FIXED_POINT
void idct_fix(const Word16* in, Word16* out);
void dct_fix(const Word16* in, Word16* out);
Word16 pow2_16(Word16 x, Word16* y_e);
Word32 Isqrt(Word32 x, /* mantissa */
Word16* x_e /* pointer to exponent */
);
#else
void dct(
double* x, // i: input
double* y // o: dct output
);
void idct(
double* x, // i:input
double* y // o:idct output
);
#endif
void duplicate_q15(Word16* src, Word16* dst, Word32 size);
void duplicate_q31(Word32* src, Word32* dst, Word32 size);
void shift_q15(Word16 x[], /* i/o: signal to scale Qx */
const Word16 lg, /* i : size of x[] Q0 */
const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */
);
void set_q31(Word32 val, Word32* dst, Word32 size);
#endif //#if (ALG_LC3_ENABLE)
#endif
+369
View File
@@ -0,0 +1,369 @@
#ifndef _CONSTANT_H
#define _CONSTANT_H
#include "../inc/lc3_types.h"
#include "../inc/config.h"
#if (ALG_LC3_ENABLE)
#define PI 3.1415926
extern int Nms[2];
/* mdct */
#ifndef FIXED_POINT
/* W_10ms_NF for MDCT*/
extern double w_0_N80[130];
extern double w_0_N160[260];
extern double w_0_N240[390];
extern double w_0_N320[520];
extern double w_0_N480[780];
/* W_7.5ms_NF for MDCT*/
extern double w_1_N60[106];
extern double w_1_N120[212];
extern double w_1_N180[318];
extern double w_1_N240[424];
extern double w_1_N360[636];
extern double * w_Nms_NF_all[2][5];
#else
#ifdef USE_SPREAD_FFT
extern Word32 RotVector_40_32[2 * 28];
#ifndef LC3_16K_ONLY
extern Word16 RotVector_240[2 * (240 - 30)];
extern Word16 RotVector_150[150];
#endif
extern Word16 RotVector_160[2 * (160 - 20)];
//extern Word16 RotVector_120[2 * (120 - 20)];
//extern Word16 RotVector_100[100];
extern Word16 RotVector_330[330];
//extern Word16 RotVector_220[220];
#endif
/* W_10ms_NF for MDCT*/
extern Word16 w_0_N80[130];
extern Word16 w_0_N160[260];
#ifndef LC3_16K_ONLY
extern Word16 w_0_N240[390];
extern Word16 w_0_N320[520];
extern Word16 w_0_N480[780];
#endif
/* W_7.5ms_NF for MDCT*/
extern Word16 w_1_N60[106];
extern Word16 w_1_N120[212];
#ifndef LC3_16K_ONLY
extern Word16 w_1_N180[318];
extern Word16 w_1_N240[424];
extern Word16 w_1_N360[636];
#endif
#ifndef LC3_16K_ONLY
extern Word16* w_Nms_NF_all[2][5];
#else
extern Word16* w_Nms_NF_all[2][2];
#endif
/* 0x5a82799a*/
#define TWIDDLE (0x5a82)
/* twiddle for dct_IV */
extern Word16 mdct_twiddle_0_N80[80];
extern Word16 mdct_twiddle_0_N160[160];
#ifndef LC3_16K_ONLY
extern Word16 mdct_twiddle_0_N240[240];
extern Word16 mdct_twiddle_0_N320[320];
extern Word16 mdct_twiddle_0_N480[480];
#endif
extern Word16 mdct_twiddle_1_N60[60];
extern Word16 mdct_twiddle_1_N120[120];
#ifndef LC3_16K_ONLY
extern Word16 mdct_twiddle_1_N180[180];
extern Word16 mdct_twiddle_1_N240[240];
extern Word16 mdct_twiddle_1_N360[360];
#endif
#ifndef LC3_16K_ONLY
extern Word16* mdct_twiddle_all[2][5];
#else
extern Word16* mdct_twiddle_all[2][2];
#endif
/* sin_twiddle for dct_IV*/
extern Word16 mdct_sin_twiddle_161[];
extern Word16 mdct_sin_twiddle_181[];
extern Word16 mdct_sin_twiddle_241[];
/* sin_step for dct_IV */
extern Word16 mdct_sin_step_all[5];
extern Word16 InvIntTable[32];
#endif // !FIXED_PONIT
extern Word32 I_8000[65];
extern Word32 I_16000[65];
#ifndef LC3_16K_ONLY
extern Word32 I_24000[65];
extern Word32 I_32000[65];
extern Word32 I_48000[65];
#endif
extern Word32 I_8000_7_5ms[61];
extern Word32 I_16000_7_5ms[65];
#ifndef LC3_16K_ONLY
extern Word32 I_24000_7_5ms[65];
extern Word32 I_32000_7_5ms[65];
extern Word32 I_48000_7_5ms[65];
#endif
#ifndef LC3_16K_ONLY
extern Word32 * I_FS[2][5];
#else
extern Word32* I_FS[2][2];
#endif
extern Word16 bands_nrg_scale[32];
/* bw detector */
extern Word32 Ibw_start_16000_10ms[4];
extern Word32 Ibw_start_24000_10ms[4] ;
extern Word32 Ibw_start_32000_10ms[4] ;
extern Word32 Ibw_start_48000_10ms[4] ;
extern Word32 Ibw_start_16000_7_5ms[4] ;
extern Word32 Ibw_start_24000_7_5ms[4] ;
extern Word32 Ibw_start_32000_7_5ms[4] ;
extern Word32 Ibw_start_48000_7_5ms[4] ;
extern Word32* Ibw_start_all_10ms[4] ;
extern Word32* Ibw_start_all_7_5ms[4];
extern Word32 Ibw_stop_16000_10ms[4] ;
extern Word32 Ibw_stop_24000_10ms[4] ;
extern Word32 Ibw_stop_32000_10ms[4] ;
extern Word32 Ibw_stop_48000_10ms[4];
extern Word32 Ibw_stop_16000_7_5ms[4] ;
extern Word32 Ibw_stop_24000_7_5ms[4];
extern Word32 Ibw_stop_32000_7_5ms[4] ;
extern Word32 Ibw_stop_48000_7_5ms[4] ;
extern Word32* Ibw_stop_all_10ms[4] ;
extern Word32* Ibw_stop_all_7_5ms[4] ;
extern Word32 L_10ms[4];
extern Word32 L_7_5ms[4];
extern Word16 bw_nbits_tab[5];
extern Word32 BW_thresh_quiet[4] ;
extern Word16 BW_thresh_quiet_exp ;
/* sns */
extern Word16 g_tilt_8000[64];
extern Word16 g_tilt_8000_e[64];
extern Word16 g_tilt_16000[64];
extern Word16 g_tilt_16000_e[64];
#ifndef LC3_16K_ONLY
extern Word16 g_tilt_24000[64];
extern Word16 g_tilt_24000_e[64];
extern Word16 g_tilt_32000[64];
extern Word16 g_tilt_32000_e[64];
extern Word16 g_tilt_48000[64];
extern Word16 g_tilt_48000_e[64];
#endif
#ifndef LC3_16K_ONLY
extern Word16* g_tilt_all[5];
extern Word16* g_tilt_all_e[5];
#else
extern Word16* g_tilt_all[2];
extern Word16* g_tilt_all_e[2];
#endif
extern Word16 isqrt_Q16tab[1 + 64];
extern Word32 ISqrtTable[32];
extern Word16 ISqrtDiffTable[32];
#ifdef FIXED_POINT
extern Word16 LFCB_fix[256];
extern Word16 HFCB_fix[256];
#else
extern double LFCB[256];
extern double HFCB[256];
#endif
#ifdef FIXED_POINT
extern Word16 sns_vq_reg_adj_gains_fix[2];
extern Word16 sns_vq_reg_lf_adj_gains_fix[4];
extern Word16 sns_vq_near_adj_gains_fix[4];
extern Word16 sns_vq_far_adj_gains_fix[8];
extern Word16* sns_vq_adj_gains_fix[4];
#else
extern double sns_vq_reg_adj_gains[2] ;
extern double sns_vq_reg_lf_adj_gains[4] ;
extern double sns_vq_near_adj_gains[4] ;
extern double sns_vq_far_adj_gains[8] ;
extern double* sns_vq_adj_gains[4];
#endif
extern Word32 sns_gainMSBbits[4] ;
extern Word32 sns_gainLSBbits[4] ;
extern UWord32 MPVQ_offsets[16][11] ;
#ifndef FIXED_POINT
extern double D[256];
#endif // !FIXED_POINT
/* TNS */
extern Word16 tns_sub_start_freq_NB_10ms[6];
extern Word16 tns_sub_start_freq_WB_10ms[6];
extern Word16 tns_sub_start_freq_SSWB_10ms[6];
extern Word16 tns_sub_start_freq_SWB_10ms[6];
extern Word16 tns_sub_start_freq_FB_10ms[6];
extern Word16 tns_sub_start_freq_NB_7_5ms[6];
extern Word16 tns_sub_start_freq_WB_7_5ms[6];
extern Word16 tns_sub_start_freq_SSWB_7_5ms[6];
extern Word16 tns_sub_start_freq_SWB_7_5ms[6];
extern Word16 tns_sub_start_freq_FB_7_5ms[6];
extern Word16 tns_sub_stop_freq_NB_10ms[6];
extern Word16 tns_sub_stop_freq_WB_10ms[6];
extern Word16 tns_sub_stop_freq_SSWB_10ms[6];
extern Word16 tns_sub_stop_freq_SWB_10ms[6];
extern Word16 tns_sub_stop_freq_FB_10ms[6];
extern Word16 tns_sub_stop_freq_NB_7_5ms[6];
extern Word16 tns_sub_stop_freq_WB_7_5ms[6];
extern Word16 tns_sub_stop_freq_SSWB_7_5ms[6];
extern Word16 tns_sub_stop_freq_SWB_7_5ms[6];
extern Word16 tns_sub_stop_freq_FB_7_5ms[6];
extern Word16* tns_sub_start_freq_all[2][5];
extern Word16* tns_sub_stop_freq_all[2][5];
extern Word16 ac_tns_order_bits[2][8] ;
extern Word16 ac_tns_order_freq[2][8];
extern Word16 ac_tns_order_cumfreq[2][8];
extern Word16 ac_tns_coef_bits[8][17] ;
extern Word16 ac_tns_coef_freq[8][17] ;
extern Word16 ac_tns_coef_cumfreq[8][17] ;
extern Word32 tnsAcfWindow[8];
extern Word16 tnsQuantThr[16];
extern Word16 tnsQuantPts[17];
/* Long Term Postfiltering*/
extern Word16 resamp_params[5][4];
#ifdef FIXED_POINT
/*extern Word16 tab_resamp_filter_8k_16k[239];// Q_16k = 15,Q_8k =14
extern Word16 tab_resamp_filter_24k[239];//Q_24 = 15
extern Word16 tab_resamp_filter_32k[239];//Q_32 = 15
extern Word16 tab_resamp_filter_48k[239];//Q_48 = 15
extern Word16* tab_resamp_filter_all[5];*/
extern Word16 resamp_filt_8k[240];
extern Word16 resamp_filt_16k[240];
#ifndef LC3_16K_ONLY
extern Word16 resamp_filt_24k[240];
extern Word16 resamp_filt_32k[240];
extern Word16 resamp_filt_48k[240];
#endif
#ifndef LC3_16K_ONLY
extern Word16* resamp_filts[5];
#else
extern Word16* resamp_filts[2];
#endif
extern Word16 ltpf_ac_interp_filt[7][9];
extern Word16 inter_filter[5][4][12];
#ifdef ANDES_INTRINSIC
extern Word16 inter_filter_i[3] ;
extern Word16 inter_filter_fr[5][4][4];
#endif
extern Word16 inter_filter_shift[5];
extern Word16 inter_filter_len[5];
extern Word32 isqrt_table[128 + 2];
extern Word16 highpass50_num[3];
extern Word16 highpass50_den[2];
#ifdef ANDES_INTRINSIC
extern Word16 highpass50[6];
#endif // ANDES_INTRINSIC
extern Word16 DownSamp_h2[5]; //Q15
extern Word16 R_6k4_corr_weighting[98];
extern Word16 tab_ltpf_interp_R[31];
#else
extern double tab_resamp_filter[239];
extern double tab_ltpf_interp_R[31];
extern double h12k8_coef_4[240];
extern double h12k8_coef_3[240];
extern double h12k8_coef_2[240];
extern double h12k8_coef_1[240];
extern double h12k8_coef_0[240];
extern double* h12k8_coef_all[5];
extern double highpass50_num[3];
extern double highpass50_den[2];
extern double DownSamp_h2[5];
extern double R_6k4_corr_weighting[98];
extern double tab_ltpf_interp_x12k8[15];
#endif // FIXED_POINT
#define LTPF_K_MAX 114
#define LTPF_K_MIN 17
#ifdef FIXED_POINT
extern Word16 tab_ltpf_num_8000_fix[4 * 3];
extern Word16 tab_ltpf_num_16000_fix[4 * 3];
#ifndef LC3_16K_ONLY
extern Word16 tab_ltpf_num_24000_fix[4 * 5];
extern Word16 tab_ltpf_num_32000_fix[4 * 7];
extern Word16 tab_ltpf_num_48000_fix[4 * 11];
#endif
#ifndef LC3_16K_ONLY
extern Word16* tab_ltpf_num_fix[5];
#else
extern Word16* tab_ltpf_num_fix[2];
#endif
extern Word16 tab_ltpf_den_8000_fix[4 * 5];
extern Word16 tab_ltpf_den_16000_fix[4 * 5];
#ifndef LC3_16K_ONLY
extern Word16 tab_ltpf_den_24000_fix[4 * 7];
extern Word16 tab_ltpf_den_32000_fix[4 * 9];
extern Word16 tab_ltpf_den_48000_fix[4 * 13];
#endif
#ifndef LC3_16K_ONLY
extern Word16* tab_ltpf_den_fix[5];
#else
extern Word16* tab_ltpf_den_fix[2];
#endif
#else
extern double tab_ltpf_num_8000[4*3];
extern double tab_ltpf_num_16000[4*3];
extern double tab_ltpf_num_24000[4*5];
extern double tab_ltpf_num_32000[4*7];
extern double tab_ltpf_num_48000[4*11];
extern double* tab_ltpf_num[5];
extern double tab_ltpf_den_8000[4*5];
extern double tab_ltpf_den_16000[4*5];
extern double tab_ltpf_den_24000[4*7];
extern double tab_ltpf_den_32000[4*9];
extern double tab_ltpf_den_48000[4*13];
extern double* tab_ltpf_den[5];
#endif
extern Word16 tab_ltpf_num_len[5];
extern Word16 tab_ltpf_den_len[5];
/* spectral data */
#define NBITS_SNS 38
#define NBITS_GAIN 8
#define NBITS_NF 3
extern UWord8 ac_spec_lookup[4096];
extern Word16 ac_spec_cumfreq[64][17];
extern Word16 ac_spec_freq[64][17];
extern Word16 ac_spec_bits[64][17];
extern Word16 Tab_esc_nb[4];
extern Word32 global_gain_tab[28];
extern Word16 global_gain_t1[5];
extern Word16 global_gain_t2[5];
extern Word16 global_gain_t3[5];
extern Word16 global_gain_t4[5];
extern Word16 global_gain_t5[5];
/* noise estimation */
extern Word16 bw_stop_10ms[5];
extern Word16 bw_stop_7_5ms[5];
/* basic op */
extern Word32 Log2_16_table1[16];
extern Word16 Log2_16_table2[16] ;
extern Word16 ldCoeff[7];
/* table for 2^x */
extern UWord32 exp2x_tab_long[32] ;
extern UWord32 exp2_tab_long[32] ;
extern UWord32 exp2w_tab_long[32];
/* 1/x tables */
extern Word32 InvTable[32];
extern Word16 InvDiffTable[32];
#endif //#if (ALG_LC3_ENABLE)
#endif // CONSTANT_H
+120
View File
@@ -0,0 +1,120 @@
#ifndef __DUMP_H__
#define __DUMP_H__
#define DUMP_INPUT 0x1
#define DUMP_MDCT 0x2;
/* encoder part */
#define FILE_MDCT "enc_mdct.txt"
#define FILE_ENERGY "enc_energy.txt"
#define FILE_BW_D "enc_bw_detector.txt"
#define FILE_SNS "enc_sns.txt"
#define FILE_SNS_SCF "enc_sns_scf.txt"
#define FILE_TNS_X_F "enc_tns_X_F_f.txt"
/* decoder part */
#define FILE_DEC_ARI "dec_arithmatic.txt"
#define FILE_DEC_RES "dec_residual.txt"
#define FILE_DEC_NF "dec_noisefilling.txt"
#define FILE_DEC_GG "dec_globalgain.txt"
#define FILE_DEC_TNS "dec_tns.txt"
#define FILE_DEC_SNS "dec_sns.txt"
#define FILE_DEC_IMDCT "dec_imdct.txt"
#define FILE_DEC_LTPF "dec_ltpf.txt"
#define FILE_DEC_SNS_SCF "dec_sns_scf.txt"
#define FILE_DEC_SNS_G_SNS "dec_sns_g_sns.txt"
#define FILE_LTPF_X_12k8_D "ltpf_x12k8_D.txt"
#define DUMP_FLAG (DUMP_MDCT)
#define FILE_OPEN(fp, name) \
fp = fopen(name, "w"); \
if (fp == NULL) { \
printf("failed to open %s\n", name); \
return -1; \
}
int dump_open();
void dump_close();
void dump_dec_arithmatic(short* in, int len);
void dump_dec_residual(int* in, short exponent, int len);
void dump_dec_residual_f(double* in, int len);
void dump_dec_noisefilling(int* in, short exponent, int len);
void dump_dec_noisefilling_f(double* in, int len);
void dump_dec_global_gain(int* in, short exponent, int len);
void dump_dec_global_gain_f(double* in, int len);
void dump_dec_tns(int* in, short exponent, int len);
void dump_dec_tns_f(double* in, int len);
void dump_dec_sns(int* in, short exponent, int len);
void dump_dec_sns_f(double* in, int len);
void dump_dec_sns_scf(short* inbuf, short exponent, short len);
void dump_dec_sns_scf_f(double* inbuf, short len);
void dump_dec_sns_g_sns(short* inbuf, short* exponent, short len);
void dump_dec_sns_g_sns_f(double* inbuf, short len);
void dump_dec_imdct1(int* inbuf, short exponent, short len);
void dump_dec_imdct(short* inbuf, short exponent, short len);
void dump_dec_imdct_f(double* inbuf, short len);
void dump_dec_ltpf(short* inbuf, short exponent, short len);
void dump_dec_ltpf1(int* inbuf, short exponent, short len);
void dump_dec_ltpf_f(double* inbuf, short len, short ltpf_active);
void dump_mdct(int* inbuf, short exponent, short len);
void dump_mdct_f(double* inbuf, short len);
void dump_energy(int* inbuf, short exponent, short len);
void dump_energy_f(double* inbuf, short len);
void dump_bw_detector(int bw_idx);
void dump_sns(int* inbuf, short exponent, short len);
void dump_sns_f(double* inbuf, short len);
void dump_sns_scf(short* inbuf, short exponent, short len);
void dump_sns_scf_f(double* inbuf, short len);
void dump_sns_index(int index_LF, int index_HF);
void dump_tns_X_F(int* inbuf, short exponent, short len);
void dump_tns_X_F_f(double* inbuf, short len);
void dump_sq_X_q_f(short* X_q, short len);
void dump_ltpf_x_tilde_12k8D_f(double* inbuf, short len);
void dump_ltpf_x_tilde_12k8D(short* input, short exponent, short len);
void dump_bw0(int bw0);
void dump_sns_shape_index(int shape_j);
void dump_sns_y(short* y0, short* y1, short* y2, short* y3);
void dump_sns_t2_rot(short* t2_rot, short len);
void dump_sns_t2_rot_f(double* t2_rot, short len);
void dump_sns_E_P(int* input, short* exponent, short len);
void dump_sns_E_4_f(double* E_4, short len);
void dump_sns_E_4(int* input, short* exponent, short len);
void dump_sns_r1_f(double* input, short len);
void dump_sns_r1(short* input, short len);
void dump_sns_scf_q(short* input, short exponent, short len);
void dump_sns_scf_q_f(double* input, short len);
void dump_sns_scf_q_int(short* input, short exponent, short len);
void dump_sns_scf_q_int_f(double* input, short len);
void dump_tns_nbits_tns(short input);
void dump_tns_tns_lpc_weighting(short input);
void dump_tns_rc_order(short* input, short len);
void dump_tns_rc_int(short* input, short len);
void dump_ltpf_active(short input);
void dump_ltpf_pitch_index(int input);
void dump_x_6k4(short* input, short exponent);
void dump_x_12k8_HP(short* input, short exponent, int len);
void dump_x_12k8_HP_f(double* input);
void dump_ltpf_nc_T_f(double input);
void dump_ltpf_nc_T(short input, short exponent);
void dump_side_information(char* input, int len);
void dump_mdct_input(int* input, short exponent, int len);
void dump_tda_x_hp(short* input, int len);
void dump_F_att(short input);
void dump_short_data(short input);
void dump_short_matric(short* input, int len);
void dump_int_data(int input);
void dump_int_matric(int* input, int len);
void dump_sq_X_q(short* input, int len);
void dump_res_bits(char* input, int len);
void dump_F_NF(short input);
void dump_output(char* input, int len);
void dump_pitch_present(int input);
void dump_ltpf_bits(int input);
void dump_ltpf_x6k4(short* input, int len);
void dump_mdct_output(int* input, short exponent, int len);
#endif
+116
View File
@@ -0,0 +1,116 @@
#ifndef _ENCODER_FUNCTION_H
#define _ENCODER_FUNCIION_H
#include"../inc/lc3_enc.h"
#if (ALG_LC3_ENABLE)
#include<stdlib.h>
//#include<stdio.h>
#include "fft_lib/_kiss_fft_guts.h"
#include"constant.h"
#include"../inc/config.h"
#include"intrinsic.h"
#include"dump.h"
#include"basic_op.h"
#include"common_func.h"
#ifndef FIXED_POINT
void ld_mdct(LC3_ENC_STRU*enc,Word16 *input,double *X,double *E_B);
void bw_detector(LC3_ENC_STRU* enc, double* E_B, Word16* Pbw);
void tda_detector(LC3_ENC_STRU* enc, Word16* input, Word32* Fatt);
void sns(
LC3_ENC_STRU* enc, // i
Word32 F_att, // i: attack flag
double* X, // i: frequancy data
double* E_B, // i: frequancy bands energy
double* X_S, // o: frequanct data after SNS
Word16* ind_LF, // o: codebook index for LF vector
Word16* ind_HF, // o: codebook index for HF vector
Word16* shape_j, // o: shape index for pyramid vector
Word32* PVQ_PARA // o: PVQ parameter
);
void tns(LC3_ENC_STRU* enc, Word32 Pbw, double* X_S, Word16 num_tns_filter, Word16* rc_int,
Word16* rc_order, double* X_F, double* max_abs_X_F, Word16* nbits_TNS, Word16* tns_lpc_weighting);
void ltpf(LC3_ENC_STRU* enc, Word16* input, Word32* pitch_present, Word32* ltpf_active, Word32* pitch_index, Word16* nbits_LTPF);
void spectral_quantization(LC3_ENC_STRU* enc, Word32 nbits_bw, Word32 nbits_TNS, Word32 nbits_LTPF, double* X_F,
double max_abs_X_F, Word16* X_q, Word32* nbits_spec, Word32* nbits_trunc, double* gg, Word16* gg_ind, Word16* lsbMode, Word16* lastnz_trunc, Word16* rateFlag);
void residual_coding_encoder(LC3_ENC_STRU* enc, Word32 nbits_residual_max, Word16* X_q,
double* X_F, double gg, Word16* res_bits, Word32* nbits_residual);
void noise_estimation_encoder(LC3_ENC_STRU* enc, Word16* X_q, Word32 Pbw, double* X_f, double gg, Word16* F_NF);
void bitstream_encoder(
LC3_ENC_STRU* enc, // i
Word16 nbits_bw, Word16 P_bw, // i: bw_detector
Word16 ind_LF, Word16 ind_HF, Word16 shape_j, Word32* SNS_VQ_ORDER, // i: sns
Word16 num_tns_filters, Word16* rc_order, Word16 tns_lpc_weighting, Word16* rc_i, Word16* X_q, // i: tns
Word16 pitch_present, Word16 ltpf_active, Word16 pitch_index, // i: ltpf
Word16 lastnz_trunc, Word16 lsbMode, Word16 gg_ind, Word16 rateFlag, // i: spectral quantization
Word32 nbits_residual, Word16* res_bits, // i: residual coding
Word16 F_NF, // i: noise level estimation
UWord8* bytes // o: bitstream
);
#else
void dct_IV(Word32 nMs_mode, Word16 fs_ind, Word32* dct_input, kiss_fft_state16_ptr kiss_fft_state, Word16 NF, Word16* data_exp);
void ld_mdct(LC3_ENC_STRU* enc, Word16* input, Word32* X, Word32* E_B,Word16* data_exp, Word16* E_B_exp);
void bw_detector(
LC3_ENC_STRU* enc, // i
Word32* E_B, // i:from ld_mdct
Word16 E_B_exp,
Word16* Pbw // o:P_bw
);
void tda_detector(
LC3_ENC_STRU* enc, // i
Word16* input, // i:input data
Word16* F_att // o:attack Flag
);
void sns(
LC3_ENC_STRU* enc, // i
Word16 F_att, // i: attack flag
Word32* X, // i: frequancy data
Word32* E_B, // i: frequancy bands energy
Word16* E_B_exp, // i: exp of E_B
Word32* X_S, // o: frequanct data after SNS
Word16* ind_LF, // o: codebook index for LF vector
Word16* ind_HF, // o: codebook index for HF vector
Word16* shape_j, // o: shape index for pyramid vector
Word32* PVQ_PARA // o: PVQ parameter
);
void tns(LC3_ENC_STRU* enc, Word32 Pbw, Word32* X_S, Word16 num_tns_filter,Word32 near_nyquist_flag, Word16* rc_int, Word16* rc_order, Word32* X_F, Word16* nbits_TNS, Word16* tns_lpc_weighting);
void ltpf(LC3_ENC_STRU* enc, Word16* input, Word32* pitch_present, Word32* ltpf_active, Word32* pitch_index, Word16* nbits_LTPF, Word16 ltpf_enable);
void spectral_quantization(
LC3_ENC_STRU* enc, Word16 nbits_bw, Word16 nbits_TNS, Word16 nbits_LTPF, Word32* X_F, Word16 X_exp,
Word16* X_q, Word16* nbits_spec, Word16* nbits_trunc, Word16* gg, Word16* gg_e,
Word16* gg_ind, Word16* lsbMode, Word16* lastnz_trunc, Word16* rateFlag, Word16* codingdata);
void residual_coding_encoder(LC3_ENC_STRU* enc, Word16 nbits_residual_max, Word16* X_q,
Word32* X_F, Word16 X_exp, Word16 gg, Word16 gg_e, Word8* res_bits, Word16* nbits_residual);
void noise_estimation_encoder(LC3_ENC_STRU* enc, Word16* X_q, Word32 Pbw,
Word32* X_f, Word16 X_exp, Word16 gg, Word16 gg_e, Word16* F_NF);
void bitstream_encoder(
LC3_ENC_STRU* enc, // i
Word16 nbits_bw, Word16 P_bw, // i: bw_detector
Word16 ind_LF, Word16 ind_HF, Word16 shape_j, Word32* PVQ_PARA, // i: sns
Word16 num_tns_filters, Word16* rc_order, Word16 tns_lpc_weighting, Word16* rc_i, Word16* X_q, // i: tns
Word16 pitch_present, Word16 ltpf_active, Word16 pitch_index, // i: ltpf
Word16 lastnz_trunc, Word16 lsbMode, Word16 gg_ind, Word16 rateFlag, Word16* codingdata, // i: spectral quantization
Word32 nbits_residual, Word8* res_bits, // i: residual coding
Word16 F_NF, // i: noise level estimation
UWord8* bytes // o: bitstream
);
#endif // FIXED_POINT
#endif //#if (ALG_LC3_ENABLE)
#endif
+190
View File
@@ -0,0 +1,190 @@
/*
Copyright (c) 2003-2010, Mark Borgerding
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __KISS_FFT_GUTS_H__
#define __KISS_FFT_GUTS_H__
#ifndef USE_SPREAD_FFT
#include "../../inc/lc3_types.h"
#if (ALG_LC3_ENABLE)
/* kiss_fft.h
defines kiss_fft_scalar as either short or a float type
and defines
typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
#include "kiss_fft.h"
//#include <limits.h>
#include "../../inc/config.h"
#include "../intrinsic.h"
#define MAXFACTORS 32
/* e.g. an fft of length 128 has 4 factors
as far as kissfft is concerned
4*4*4*2
struct kiss_fft_state{
int nfft;
int inverse;
int factors[2*MAXFACTORS];
kiss_fft_cpx twiddles[1];
};
*/
/*
Explanation of macros dealing with complex math:
C_MUL(m,a,b) : m = a*b
C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise
C_SUB( res, a,b) : res = a - b
C_SUBFROM( res , a) : res -= a
C_ADDTO( res , a) : res += a
* */
#ifdef FIXED_POINT
#if (FIXED_POINT==32)
# define FRACBITS 31
# define SAMPPROD Word64
#define SAMP_MAX 2147483647
#else
# define FRACBITS 15
# define SAMPPROD Word32
#define SAMP_MAX 32767
#endif
#define SAMP_MIN -SAMP_MAX
#if defined(CHECK_OVERFLOW)
# define CHECK_OVERFLOW_OP(a,op,b) \
if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); }
#endif
# define smul(a,b) ( (SAMPPROD)(a)*(b) )
# define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS )
#if 0
# define S_MUL(a,b) sround( smul(a,b) )
# define C_MUL(m,a,b) \
do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
(m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
# define DIVSCALAR(x,k) \
(x) = sround( smul( x, SAMP_MAX/k ) )
# define C_MULBYSCALAR( c, s ) \
do{ (c).r = sround( smul( (c).r , s ) ) ;\
(c).i = sround( smul( (c).i , s ) ) ; }while(0)
#else
# define S_MUL(a,b) ( mult_r_32_Q31_32(a,b) )
# define C_MUL(m,a,b) \
do{ (m).r = ( mult_r_32_Q31_32((a).r,(b).r) - mult_r_32_Q31_32((a).i,(b).i) ); \
(m).i = ( mult_r_32_Q31_32((a).r,(b).i) + mult_r_32_Q31_32((a).i,(b).r) ); }while(0)
# define DIVSCALAR(x,k) \
(x) = ( mult_r_32_Q31_32( x, SAMP_MAX/k ) )
# define C_MULBYSCALAR( c, s ) \
do{ (c).r = ( mult_r_32_Q31_32( (c).r , s ) ) ;\
(c).i = ( mult_r_32_Q31_32( (c).i , s ) ) ; }while(0)
#endif
# define C_FIXDIV(c,div) \
do { DIVSCALAR( (c).r , div); \
DIVSCALAR( (c).i , div); }while (0)
#else /* not FIXED_POINT*/
# define S_MUL(a,b) ( (a)*(b) )
#define C_MUL(m,a,b) \
do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
(m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
# define C_FIXDIV(c,div) /* NOOP */
# define C_MULBYSCALAR( c, s ) \
do{ (c).r *= (s);\
(c).i *= (s); }while(0)
#endif
#ifndef CHECK_OVERFLOW_OP
# define CHECK_OVERFLOW_OP(a,op,b) /* noop */
#endif
#define C_ADD( res, a,b)\
do { \
CHECK_OVERFLOW_OP((a).r,+,(b).r)\
CHECK_OVERFLOW_OP((a).i,+,(b).i)\
(res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \
}while(0)
#define C_SUB( res, a,b)\
do { \
CHECK_OVERFLOW_OP((a).r,-,(b).r)\
CHECK_OVERFLOW_OP((a).i,-,(b).i)\
(res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \
}while(0)
#define C_ADDTO( res , a)\
do { \
CHECK_OVERFLOW_OP((res).r,+,(a).r)\
CHECK_OVERFLOW_OP((res).i,+,(a).i)\
(res).r += (a).r; (res).i += (a).i;\
}while(0)
#define C_SUBFROM( res , a)\
do {\
CHECK_OVERFLOW_OP((res).r,-,(a).r)\
CHECK_OVERFLOW_OP((res).i,-,(a).i)\
(res).r -= (a).r; (res).i -= (a).i; \
}while(0)
#ifdef FIXED_POINT
# define KISS_FFT_COS(phase) floor(.5+SAMP_MAX * cos (phase))
# define KISS_FFT_SIN(phase) floor(.5+SAMP_MAX * sin (phase))
# define HALF_OF(x) ((x)>>1)
#elif defined(USE_SIMD)
# define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
# define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
# define HALF_OF(x) ((x)*_mm_set1_ps(.5))
#else
# define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
# define HALF_OF(x) ((x)*.5)
#endif
#define kf_cexp(x,phase) \
do{ \
(x)->r = KISS_FFT_COS(phase);\
(x)->i = KISS_FFT_SIN(phase);\
}while(0)
/* a debugging function */
#define pcpx(c)\
fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) )
#ifdef KISS_FFT_USE_ALLOCA
// define this to allow use of alloca instead of malloc for temporary buffers
// Temporary buffers are used in two case:
// 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5
// 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an in-place transform.
#include <alloca.h>
#define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes)
#define KISS_FFT_TMP_FREE(ptr)
#else
#define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes)
#define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr)
#endif
#endif //#if (ALG_LC3_ENABLE)
#endif
#endif
+128
View File
@@ -0,0 +1,128 @@
#ifndef KISS_FFT_H
#define KISS_FFT_H
#include "../../inc/config.h"
#ifndef USE_SPREAD_FFT
#include "../../inc/lc3_types.h"
#include "../../inc/config.h"
#if (ALG_LC3_ENABLE)
#ifdef __cplusplus
extern "C" {
#endif
/*
ATTENTION!
If you would like a :
-- a utility that will handle the caching of fft objects
-- real-only (no imaginary time component ) FFT
-- a multi-dimensional FFT
-- a command-line utility to perform ffts
-- a command-line utility to perform fast-convolution filtering
Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c
in the tools/ directory.
*/
#ifdef USE_SIMD
# include <xmmintrin.h>
# define kiss_fft_scalar __m128
#define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16)
#define KISS_FFT_FREE _mm_free
#else
#define KISS_FFT_MALLOC malloc
#define KISS_FFT_FREE free
#endif
#ifdef FIXED_POINT
//#include <sys/types.h>
# if (FIXED_POINT == 32)
# define kiss_fft_scalar Word32
# else
# define kiss_fft_scalar Word16
# endif
#else
# ifndef kiss_fft_scalar
/* default is float */
# define kiss_fft_scalar float
# endif
#endif
/*
typedef struct {
kiss_fft_scalar r;
kiss_fft_scalar i;
}kiss_fft_cpx;
typedef struct kiss_fft_state* kiss_fft_cfg;
*/
/*
* kiss_fft_alloc
*
* Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
*
* typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL);
*
* The return value from fft_alloc is a cfg buffer used internally
* by the fft routine or NULL.
*
* If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc.
* The returned value should be free()d when done to avoid memory leaks.
*
* The state can be placed in a user supplied buffer 'mem':
* If lenmem is not NULL and mem is not NULL and *lenmem is large enough,
* then the function places the cfg in mem and the size used in *lenmem
* and returns mem.
*
* If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough),
* then the function returns NULL and places the minimum cfg
* buffer size in *lenmem.
* */
kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,unsigned int * lenmem);
/*
* kiss_fft(cfg,in_out_buf)
*
* Perform an FFT on a complex input buffer.
* for a forward FFT,
* fin should be f[0] , f[1] , ... ,f[nfft-1]
* fout will be F[0] , F[1] , ... ,F[nfft-1]
* Note that each element is complex and can be accessed like
f[k].r and f[k].i
* */
void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
/*
A more generic version of the above function. It reads its input from every Nth sample.
* */
void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride);
/* If kiss_fft_alloc allocated a buffer, it is one contiguous
buffer and can be simply free()d when no longer needed*/
#define kiss_fft_free free
/*
Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up
your compiler output to call this before you exit.
*/
void kiss_fft_cleanup(void);
/*
* Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5)
*/
int kiss_fft_next_fast_size(int n);
/* for real ffts, we need an even size */
#define kiss_fftr_next_fast_size_real(n) \
(kiss_fft_next_fast_size( ((n)+1)>>1)<<1)
#ifdef __cplusplus
}
#endif
#endif //#if (ALG_LC3_ENABLE)
#endif
#endif // !1
@@ -0,0 +1,13 @@
#ifndef KISS_FFT_CUSTOM_H
#define KISS_FFT_CUSTOM_H
#include "../../../inc/config.h"
#if (ALG_LC3_ENABLE)
#include "kiss_fft_type.h"
void kiss_fft_32_16(kiss_fft_state16_ptr cfg, const kiss_fft_cpx_data_32* fin, kiss_fft_cpx_data_32* fout);
kiss_fft_state16_ptr kiss_fft_init_32_16(int nfft, int inverse_fft);
#endif //#if (ALG_LC3_ENABLE)
#endif
@@ -0,0 +1,189 @@
#ifndef FIXED_OP_H
#define FIXED_OP_H
#include "../../../inc/config.h"
#if (ALG_LC3_ENABLE)
#if __riscv
#include <nds_intrinsic.h>
#endif
#define QCONST16(x,bits) ((short)(.5+(x)*(((int)1)<<(bits))))
#define QCONST32(x,bits) ((int)(.5+(x)*(((int)1)<<(bits))))
#define NEG16(x) (-(x))
#define NEG32(x) (-(x))
#define EXTRACT16(x) ((short)(x))
#define EXTEND32(x) ((int)(x))
#define SHR16(a,shift) ((a) >> (shift))
#define SHL16(a,shift) ((a) << (shift))
#define SHR32(a,shift) ((a) >> (shift))
#define SHL32(a,shift) ((a) << (shift))
#define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift))
#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift))
#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
#define SHR(a,shift) ((a) >> (shift))
#define SHL(a,shift) ((int)(a) << (shift))
#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
#define ADD16(a,b) ((short)((short)(a)+(short)(b)))
#define SUB16(a,b) ((short)(a)-(short)(b))
#define ADD32(a,b) ((int)(a)+(int)(b))
#define SUB32(a,b) ((int)(a)-(int)(b))
/* result fits in 16 bits */
#define MULT16_16_16(a,b) ((((short)(a))*((short)(b))))
/* (int)(short) gives TI compiler a hint that it's 16x16->32 multiply */
#define MULT16_16(a,b) (((int)(short)(a))*((int)(short)(b)))
#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b))))
#define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12))
#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13))
#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14))
#define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))
#define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11)))
#define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15))
#define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))
#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)))
#define MAC16_16_Q11(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),11)))
#define MAC16_16_Q13(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),13)))
#define MAC16_16_P13(c,a,b) (ADD32((c),SHR(ADD32(4096,MULT16_16((a),(b))),13)))
#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11))
#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13))
#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14))
#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15))
#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13))
#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14))
#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15))
#define MUL_16_32_R15(a,bh,bl) ADD32(MULT16_16((a),(bh)), SHR(MULT16_16((a),(bl)),15))
#define MULT32_16_Q15(a,b) ((long long int)a*(long long int)b>>15)
#define MULT32_16_P15(a,b) (((long long int)a*(long long int)b+(1<<14))>>15)
#define DIV32_16(a,b) ((short)(((int)(a))/((short)(b))))
#define PDIV32_16(a,b) ((short)(((int)(a)+((short)(b)>>1))/((short)(b))))
#define DIV32(a,b) (((int)(a))/((int)(b)))
#define PDIV32(a,b) (((int)(a)+((short)(b)>>1))/((int)(b)))
# define smul(a,b) ( (int)(a)*(b) )
# define sround( x ) (short)( ( (x) + (1<<(15-1)) ) >> 15 )
# define smul32(a,b) ( (long long int)(a)*(b) )
# define sround32( x ) (int)( ( (x) + (1<<(15-1)) ) >> 15 )
# define S_MUL(a,b) sround( smul(a,b) )
#if __riscv
# define S_MUL32(a,b) ( __nds__kmmwb2_u(a,b) )
#else
# define S_MUL32(a,b) sround32( smul32(a,b) )
#endif
# define C_MUL_16_16(m,a,b) \
do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
(m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
#if __riscv
/*
# define C_MUL_32_16(m,a,b) \
do{ (m).r = ( __nds__kmmwb2_u((a).r,(b).r) - __nds__kmmwb2_u((a).i,(b).i) ); \
(m).i = __nds__kmmawb2_u( __nds__kmmwb2_u((a).r,(b).i) , (a).i,(b).r ); }while(0)
*/
# define C_MUL_32_16(m,a,b) \
do{ (m).r = ( __nds__kmmwb2_u((a).r,(b).r) - __nds__kmmwb2_u((a).i,(b).i) ); \
(m).i = ( __nds__kmmwb2_u((a).r,(b).i) + __nds__kmmwb2_u((a).i,(b).r) ); }while(0)
#else
# define C_MUL_32_16(m,a,b) \
do{ (m).r = (sround32 (smul32((a).r,(b).r)) - sround32 (smul32((a).i,(b).i)) ); \
(m).i = (sround32 (smul32((a).r,(b).i)) + sround32(smul32((a).i,(b).r)) ); }while(0)
#endif
// C_MUL4 ½á¹ûÓÒÒÆ17λ
# define C_MUL4(m,a,b) \
do{ (m).r = PSHR32( smul((a).r,(b).r) - smul((a).i,(b).i),17 ); \
(m).i = PSHR32( smul((a).r,(b).i) + smul((a).i,(b).r),17 ); }while(0)
# define DIVSCALAR(x,k) \
(x) = sround( smul( x, 32767/k ) )
# define C_FIXDIV(c,div) \
do { DIVSCALAR( (c).r , div); \
DIVSCALAR( (c).i , div); }while (0)
# define C_MULBYSCALAR( c, s ) \
do{ (c).r = sround( smul( (c).r , s ) ) ;\
(c).i = sround( smul( (c).i , s ) ) ; }while(0)
#if __riscv
# define C_MULBYSCALAR_32( c, s ) \
do{ (c).r = ( __nds__kmmwb2_u( (c).r , s ) ) ;\
(c).i = ( __nds__kmmwb2_u( (c).i , s ) ) ; }while(0)
#else
# define C_MULBYSCALAR_32( c, s ) \
do{ (c).r = sround32( smul32( (c).r , s ) ) ;\
(c).i = sround32( smul32( (c).i , s ) ) ; }while(0)
#endif
#define C_ADD( res, a,b)\
do { \
(res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \
}while(0)
#define C_SUB( res, a,b)\
do { \
(res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \
}while(0)
#if __riscv
#define C_ADD_HALF( res, a,b)\
do { \
(res).r=__nds__raddw((a).r,(b).r); (res).i=__nds__raddw((a).i,(b).i); \
}while(0)
#define C_SUB_HALF( res, a,b)\
do { \
(res).r=__nds__rsubw((a).r,(b).r); (res).i=__nds__rsubw((a).i,(b).i); \
}while(0)
#else
#define C_ADD_HALF( res, a,b)\
do { \
(res).r=((long long int)(a).r+(b).r)>>1; (res).i=((long long int)(a).i+(b).i)>>1; \
}while(0)
#define C_SUB_HALF( res, a,b)\
do { \
(res).r=((long long int)(a).r-(b).r)>>1; (res).i=((long long int)(a).i-(b).i)>>1; \
}while(0)
#endif
#define C_ADDTO( res , a)\
do { \
(res).r += (a).r; (res).i += (a).i;\
}while(0)
#define C_SUBFROM( res , a)\
do {\
(res).r -= (a).r; (res).i -= (a).i; \
}while(0)
# define HALF_OF(x) ((x)>>1)
/*
#ifdef FIXED_POINT
# define KISS_FFT_COS(phase) floor(MIN(32767,MAX(-32767,.5+32768 * cos (phase))))
# define KISS_FFT_SIN(phase) floor(MIN(32767,MAX(-32767,.5+32768 * sin (phase))))
# define HALF_OF(x) ((x)>>1)
#else
# define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
# define HALF_OF(x) ((x)*.5)
#endif
*/
#endif //#if (ALG_LC3_ENABLE)
#endif
@@ -0,0 +1,264 @@
#ifndef KISS_FFT_FUNCTION_H
#define KISS_FFT_FUNCTION_H
#include "../../../inc/config.h"
#if (ALG_LC3_ENABLE)
#include "kiss_fft_fixed_op.h"
static inline short spx_ilog2(unsigned int x)
{
int r = 0;
if (x >= (int)65536)
{
x >>= 16;
r += 16;
}
if (x >= 256)
{
x >>= 8;
r += 8;
}
if (x >= 16)
{
x >>= 4;
r += 4;
}
if (x >= 4)
{
x >>= 2;
r += 2;
}
if (x >= 2)
{
r += 1;
}
return r;
}
static inline short spx_ilog4(unsigned int x)
{
int r = 0;
if (x >= (int)65536)
{
x >>= 16;
r += 8;
}
if (x >= 256)
{
x >>= 8;
r += 4;
}
if (x >= 16)
{
x >>= 4;
r += 2;
}
if (x >= 4)
{
r += 1;
}
return r;
}
/** Generate a pseudo-random number */
static inline short speex_rand(short std, int* seed)
{
int res;
*seed = 1664525 * *seed + 1013904223;
res = MULT16_16(EXTRACT16(SHR32(*seed, 16)), std);
return EXTRACT16(PSHR32(SUB32(res, SHR32(res, 3)), 14));
}
/* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25723*x^3 (for .25 < x < 1) */
/*#define C0 3634
#define C1 21173
#define C2 -12627
#define C3 4215*/
/* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25659*x^3 (for .25 < x < 1) */
#define C0 3634
#define C1 21173
#define C2 -12627
#define C3 4204
static inline short spx_sqrt(int x)
{
int k;
int rt;
k = spx_ilog4(x) - 6;
x = VSHR32(x, (k << 1));
rt = ADD16(C0, MULT16_16_Q14(x, ADD16(C1, MULT16_16_Q14(x, ADD16(C2, MULT16_16_Q14(x, (C3)))))));
rt = VSHR32(rt, 7 - k);
return rt;
}
/* log(x) ~= -2.18151 + 4.20592*x - 2.88938*x^2 + 0.86535*x^3 (for .5 < x < 1) */
#define A1 16469
#define A2 2242
#define A3 1486
static inline short spx_acos(short x)
{
int s = 0;
short ret;
short sq;
if (x < 0)
{
s = 1;
x = NEG16(x);
}
x = SUB16(16384, x);
x = x >> 1;
sq = MULT16_16_Q13(x, ADD16(A1, MULT16_16_Q13(x, ADD16(A2, MULT16_16_Q13(x, (A3))))));
ret = spx_sqrt(SHL32(EXTEND32(sq), 13));
/*ret = spx_sqrt(67108864*(-1.6129e-04 + 2.0104e+00*f + 2.7373e-01*f*f + 1.8136e-01*f*f*f));*/
if (s)
ret = SUB16(25736, ret);
return ret;
}
#define K1 8192
#define K2 -4096
#define K3 340
#define K4 -10
static inline short spx_cos(short x)
{
short x2;
if (x < 12868)
{
x2 = MULT16_16_P13(x, x);
return ADD32(K1, MULT16_16_P13(x2, ADD32(K2, MULT16_16_P13(x2, ADD32(K3, MULT16_16_P13(K4, x2))))));
}
else {
x = SUB16(25736, x);
x2 = MULT16_16_P13(x, x);
return SUB32(-K1, MULT16_16_P13(x2, ADD32(K2, MULT16_16_P13(x2, ADD32(K3, MULT16_16_P13(K4, x2))))));
}
}
#define L1 32767
#define L2 -7651
#define L3 8277
#define L4 -626
static inline short _spx_cos_pi_2(short x)
{
short x2;
x2 = MULT16_16_P15(x, x);
return ADD16(1, MIN16(32766, ADD32(SUB16(L1, x2), MULT16_16_P15(x2, ADD32(L2, MULT16_16_P15(x2, ADD32(L3, MULT16_16_P15(L4, x2))))))));
}
static inline short spx_cos_norm(int x)
{
x = x & 0x0001ffff;
if (x > SHL32(EXTEND32(1), 16))
x = SUB32(SHL32(EXTEND32(1), 17), x);
if (x & 0x00007fff)
{
if (x < SHL32(EXTEND32(1), 15))
{
return _spx_cos_pi_2(EXTRACT16(x));
}
else {
return NEG32(_spx_cos_pi_2(EXTRACT16(65536 - x)));
}
}
else {
if (x & 0x0000ffff)
return 0;
else if (x & 0x0001ffff)
return -32767;
else
return 32767;
}
}
/*
K0 = 1
K1 = log(2)
K2 = 3-4*log(2)
K3 = 3*log(2) - 2
*/
#define D0 16384
#define D1 11356
#define D2 3726
#define D3 1301
/* Input in Q11 format, output in Q16 */
static inline int spx_exp2(short x)
{
int integer;
short frac;
integer = SHR16(x, 11);
if (integer > 14)
return 0x7fffffff;
else if (integer < -15)
return 0;
frac = SHL16(x - SHL16(integer, 11), 3);
frac = ADD16(D0, MULT16_16_Q14(frac, ADD16(D1, MULT16_16_Q14(frac, ADD16(D2, MULT16_16_Q14(D3, frac))))));
return VSHR32(EXTEND32(frac), -integer - 2);
}
/* Input in Q11 format, output in Q16 */
static inline int spx_exp(short x)
{
if (x > 21290)
return 0x7fffffff;
else if (x < -21290)
return 0;
else
return spx_exp2(MULT16_16_P14(23637, x));
}
#define M1 32767
#define M2 -21
#define M3 -11943
#define M4 4936
static inline short spx_atan01(short x)
{
return MULT16_16_P15(x, ADD32(M1, MULT16_16_P15(x, ADD32(M2, MULT16_16_P15(x, ADD32(M3, MULT16_16_P15(M4, x)))))));
}
#undef M1
#undef M2
#undef M3
#undef M4
/* Input in Q15, output in Q14 */
static inline short spx_atan(int x)
{
if (x <= 32767)
{
return SHR16(spx_atan01(x), 1);
}
else {
int e = spx_ilog2(x);
if (e >= 29)
return 25736;
x = DIV32_16(SHL32(EXTEND32(32767), 29 - e), EXTRACT16(SHR32(x, e - 14)));
return SUB16(25736, SHR16(spx_atan01(x), 1));
}
}
#define kf_cexp2(x,phase) \
do{ \
(x)->r = spx_cos_norm((phase));\
(x)->i = spx_cos_norm((phase)-32768);\
}while(0)
#endif //#if (ALG_LC3_ENABLE)
#endif // KISS_FFT_FUNCTION_H
@@ -0,0 +1,51 @@
#ifndef KISS_FFT_TYPE_H
#define KISS_FFT_TYPE_H
#include "../../../inc/config.h"
#if (ALG_LC3_ENABLE)
//#define FIXED_POINT
#define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */
#define ABS16(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 16-bit value. */
#define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 16-bit value. */
#define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */
#define ABS32(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 32-bit value. */
#define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 32-bit value. */
#define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */
typedef struct {
short r;
short i;
}kiss_fft_cpx_twiddle;
typedef struct {
short r;
short i;
}kiss_fft_cpx_data_16;
typedef struct {
short r;
short i;
}kiss_fft_cpx_twiddle_16;
typedef struct {
int r;
int i;
}kiss_fft_cpx_data_32;
#define MAX_STAGE 32
#define NFFT 240
struct kiss_fft_state16 {
int nfft;
int inverse;
int factors[2 * MAX_STAGE];
int Q_shift;
kiss_fft_cpx_twiddle_16 twiddles[NFFT];
};
typedef struct kiss_fft_state16* kiss_fft_state16_ptr;
#endif //#if (ALG_LC3_ENABLE)
#endif // !KISS_FFT_H
+8
View File
@@ -0,0 +1,8 @@
#ifndef SPREAD_FFT
#define SPREAD_FFT
#include "../../inc/lc3_types.h"
#if (ALG_LC3_ENABLE)
void BASOP_cfft(Word32* re, Word32* im, Word16 sizeOfFft, Word16 s, Word16* scale, Word32* x);
#endif //#if (ALG_LC3_ENABLE)
#endif
+6
View File
@@ -0,0 +1,6 @@
#ifndef _FUNC_ASM_H
#define _FUNC_ASM_H
Word32 dprod_q15(Word16 *src1, Word16 *src2, Word32 size);
#endif
+14
View File
@@ -0,0 +1,14 @@
#ifndef _GLOBAL_GAIN_H
#define _GLOBAL_GAIN_H
#include "../inc/lc3_dec.h"
#if (ALG_LC3_ENABLE)
#ifdef FIXED_POINT
void global_gain_fix(LC3_DEC_STRU* dec, Word32* Xq_residual, Word16 nBits, Word16* exp);
#else
void global_gain(LC3_DEC_STRU* dec, double* Xq_residual, Word16 nBits);
#endif
#endif
#endif
+727
View File
@@ -0,0 +1,727 @@
#ifndef _INTRINSIC_H
#define _INTRINSIC_H
#include "../inc/lc3_types.h"
#if (ALG_LC3_ENABLE)
#ifdef ANDES_INTRINSIC
#include <nds_intrinsic.h>
#include <nds_utils_math.h>
#endif
#ifdef ANDES_INTRINSIC
/* 16-bit Count Leading Redundant Sign */
inline Word16 clrs16(Word16 a)
{
return __nds__clrs16(a);
}
/* 32-bit count leading zero */
inline UWord32 clz32(UWord32 a) {
return __nds__clz32(a);
}
/* vin1 : Q15, vin2: Q15 ---> vout: Q15 */
inline Word16 mult_16(Word16 vin1, Word16 vin2)
{
Word16 vout;
vout = __nds__khmbb(vin1, vin2);
return vout;
}
inline Word32 mult_16_16_32(Word16 vin1, Word16 vin2)
{
return __nds__smul16(vin1, vin2);
}
/* vin1 : Q15, vin2: Q15 ---> vout: Q15 */
inline Word16 mult_r_16(Word16 vin1, Word16 vin2)
{
return __nds__sra_u(__nds__smul16(vin1, vin2),15);
}
inline Word32 mult_32(Word32 vin1, Word32 vin2)
{
return __nds__smmul(vin1, vin2);
}
/* 32-bit count leading redundant sign */
inline UWord32 clrs32(UWord32 a){
return __nds__clrs32(a);
}
/* 32-bit shift right arithmetic */
inline UWord32 sra32(UWord32 a, UWord32 b) {
return __nds__sra32(a, b);
}
inline Word32 mult_32_16_32(Word32 vin1, Word16 vin2)
{
return __nds__smmwb(vin1, (UWord32)vin2);
}
inline Word32 mult_r_32_16_32(Word32 vin1, Word16 vin2)
{
return __nds__smmwb_u(vin1, (UWord32)vin2);
}
inline Word32 mult_32_Q31_32(Word32 vin1, Word32 vin2)
{
return __nds__kwmmul(vin1, vin2);
}
inline Word32 mult_r_32_Q31_32(Word32 vin1, Word32 vin2)
{
return __nds__kwmmul_u(vin1, vin2);
}
inline Word32 mult_32_Q15_32(Word32 vin1, Word16 vin2)
{
return __nds__kmmwb2(vin1, vin2);
}
inline Word32 mult_r_32_Q15_32(Word32 vin1, Word16 vin2)
{
return __nds__kmmwb2_u(vin1, vin2);
}
inline Word32 mac_r_32_Q15_32(Word32 acc, Word32 vin1, Word16 vin2)
{
return __nds__kmmawb2_u(acc, vin1, vin2);
}
inline Word32 mac_r_32_16_32(Word32 acc, Word32 vin1, Word16 vin2)
{
return __nds__kmmawb_u(acc, vin1, vin2);
}
inline Word32 mac_16_16_32(Word32 vin, Word16 vin1, Word16 vin2)
{
return __nds__kmabb(vin, vin1, vin2);
}
inline Word32 L_shl(Word32 L_var1, Word16 var2)
{
return __nds__kslraw(L_var1, var2);
}
inline Word32 L_shr(Word32 L_var1, Word16 var2)
{
return __nds__kslraw(L_var1, -var2);
}
/*
inline Word16 lshr(Word16 var1, Word16 var2)
{
//printf("\ninput=%d %d",var1,var2);
//printf("\noutput=%d",__nds__srl16(var1, var2));
return (Word16)__nds__srl16(var1, var2);
}*/
inline Word32 L_add(Word32 L_var1, Word32 L_var2)
{
return __nds__kaddw(L_var1, L_var2);
}
inline Word32 L_sub(Word32 L_var1, Word32 L_var2)
{
return __nds__ksubw(L_var1, L_var2);
}
inline Word32 L_add_half(Word32 L_var1, Word32 L_var2)
{
return __nds__raddw(L_var1, L_var2);
}
inline Word32 L_sub_half(Word32 L_var1, Word32 L_var2)
{
return __nds__rsubw(L_var1, L_var2);
}
inline Word16 abs16(Word16 x)
{
return __nds__kabs16(x);
}
inline Word32 abs32(Word32 x)
{
return __nds__kabsw(x);
}
inline Word16 convert_q31_q15_u(Word32 x)
{
return __nds__sra_u(x, 16);
}
inline Word32 L_mult(Word16 var1, Word16 var2)
{
return __nds__kdmbb(var1, var2);
}
inline Word32 L_mac(Word32 L_var3, Word16 var1, Word16 var2)
{
return __nds__kaddw(L_var3, __nds__kdmbb(var1, var2));
}
inline Word32 L_msu(Word32 L_var3, Word16 var1, Word16 var2)
{
return __nds__ksubw(L_var3, __nds__kdmbb(var1, var2));
}
/* Multiply var1 by var2 and shift the result left by 1. Add the 32 bit
result to L_var3 with saturation. Round the LS 16 bits of the result
into the MS 16 bits with saturation and shift the result right by 16. */
inline Word16 mac_r(Word32 L_var3, Word16 var1, Word16 var2)
{
return __nds__sra_u(__nds__kaddw(L_var3, __nds__kdmbb(var1, var2)), 16);
}
inline Word16 msu_r(Word32 L_var3, Word16 var1, Word16 var2)
{
return __nds__sra_u(__nds__ksubw(L_var3, __nds__kdmbb(var1, var2)), 16);
}
#else
inline UWord32 clz32(UWord32 a) {
int i;
for (i = 32; i >= 0; i--) {
if (a == 0)
break;
a = a >> 1;
}
return i;
}
/* vin1 : Q15, vin2: Q15 ---> vout: Q15 */
inline Word16 mult_16(Word16 vin1, Word16 vin2)
{
Word32 tmp;
Word16 vout;
tmp = (Word32)vin1 * (Word32)vin2;
if (tmp == 0x40000000) {
tmp = 0x3fffffff;
}
vout = (Word16)(tmp >> 15);
return vout;
}
inline Word32 mult_16_16_32(Word16 vin1, Word16 vin2)
{
Word32 vout = (Word32)vin1 * (Word32)vin2;
return vout;
}
/* vin1 : Q15, vin2: Q15 ---> vout: Q15 */
inline Word16 mult_r_16(Word16 vin1, Word16 vin2)
{
Word32 tmp;
Word16 vout;
tmp = mult_16_16_32(vin1, vin2);
tmp += 0x4000;
vout = (Word16)(tmp >> 15);
return vout;
}
inline Word32 mult_32(Word32 vin1, Word32 vin2)
{
Word64 tmp;
Word32 vout;
tmp = (Word64)vin1 * (Word64)vin2;
vout = (Word32)(tmp >> 32);
return vout;
}
inline Word16 clrs16(Word16 a)
{
int i;
UWord32 cnt = 0;
for (i = 14; i >= 0; i--)
{
if (((a >> i) & 1) == ((a >> 15) & 1))
{
cnt++;
}
else
{
break;
}
}
return cnt;
}
inline UWord32 clrs32(UWord32 a) {
int i;
UWord32 cnt=0;
for ( i = 30; i >= 0; i--)
{
if ( ((a>>i)&1) == ((a>>31)&1) )
{
cnt++;
}
else
{
break;
}
}
return cnt;
}
inline UWord32 sra32(Word32 a, UWord32 b)
{
return a >> b;
}
inline Word32 mult_32_16_32(Word32 vin1, Word16 vin2)
{
return (Word32)(((Word64)vin1 * (Word64)vin2) >> 16);
}
inline Word32 mult_r_32_16_32(Word32 vin1, Word16 vin2)
{
Word64 round_factor = 1 << 15;
return (Word32)(((Word64)vin1 * (Word64)vin2 + round_factor) >> 16);
}
inline Word32 mult_32_Q31_32(Word32 vin1, Word32 vin2)
{
return (Word32)(((Word64)vin1 * (Word64)vin2) >> 31);
}
inline Word32 mult_r_32_Q31_32(Word32 vin1, Word32 vin2)
{
Word64 round_factor = 1 << 30;
return (Word32)(((Word64)vin1 * (Word64)vin2 + round_factor) >> 31);
}
inline Word32 mult_32_Q15_32(Word32 vin1, Word16 vin2)
{
Word64 tmp = ((Word64)vin1 * (Word64)vin2);
return (Word32)(tmp >> 15);
}
inline Word32 mult_r_32_Q15_32(Word32 vin1, Word16 vin2)
{
Word64 round_factor = 1 << 14;
Word64 tmp = ((Word64)vin1 * (Word64)vin2);
return (Word32)((tmp + round_factor) >> 15);
}
inline Word32 mac_r_32_Q15_32(Word32 acc, Word32 vin1, Word16 vin2)
{
Word64 round_factor = 1 << 14;
Word64 tmp = ((Word64)vin1 * (Word64)vin2);
return (Word32)(acc + ((tmp + round_factor) >> 15));
}
inline Word32 mac_r_32_16_32(Word32 acc, Word32 vin1, Word16 vin2)
{
Word64 round_factor = 1 << 15;
Word64 tmp = ((Word64)vin1 * (Word64)vin2);
return (Word32)(acc + ((tmp + round_factor) >> 16));
}
inline Word32 mac_16_16_32(Word32 vin, Word16 vin1, Word16 vin2)
{
Word32 vout = vin + (Word32)vin1 * (Word32)vin2;
return vout;
}
/* 32-bit logical left shift or arithmetic right shift*/
inline Word32 L_shl(Word32 L_var1, Word16 var2)
{
Word32 L_var_out = 0L;
//int Overflow = 0;
if (var2 <= 0)
{
if (var2 < -32)
var2 = -32;
var2 = -var2;
//L_var_out = L_shr(L_var1, var2);
if (var2 >= 31)
{
L_var_out = (L_var1 < 0L) ? -1 : 0;
}
else
{
if (L_var1 < 0)
{
L_var_out = ~((~L_var1) >> var2);
}
else
{
L_var_out = L_var1 >> var2;
}
}
}
else
{
for (; var2 > 0; var2--)
{
if (L_var1 > (Word32)0X3fffffffL)
{
//Overflow = 1;
L_var_out = MAX_32;
break;
}
else
{
if (L_var1 < (Word32)0xc0000000L)
{
//Overflow = 1;
L_var_out = MIN_32;
break;
}
}
L_var1 *= 2;
L_var_out = L_var1;
}
}
return (L_var_out);
}
inline Word32 L_shr(Word32 L_var1, Word16 var2)
{
Word32 L_var_out;
if (var2 < 0)
{
if (var2 < -32)
var2 = -32;
var2 = -var2;
L_var_out = L_shl(L_var1, var2);
}
else
{
if (var2 >= 31)
{
L_var_out = (L_var1 < 0L) ? -1 : 0;
}
else
{
if (L_var1 < 0)
{
L_var_out = ~((~L_var1) >> var2);
}
else
{
L_var_out = L_var1 >> var2;
}
}
}
return (L_var_out);
}
inline Word32 L_add(Word32 L_var1, Word32 L_var2)
{
Word32 L_var_out;
int Overflow = 0;
L_var_out = L_var1 + L_var2;
if (((L_var1 ^ L_var2) & 0x80000000L) == 0)
{
if ((L_var_out ^ L_var1) & 0x80000000L)
{
L_var_out = (L_var1 < 0) ? 0x80000000L : 0x7fffffffL;
Overflow = 1;
}
}
if (Overflow == 1)
{
//printf("LaddÒç³ö\n");
}
return (L_var_out);
}
inline Word32 L_sub(Word32 L_var1, Word32 L_var2)
{
Word32 L_var_out;
L_var_out = L_var1 - L_var2;
if (((L_var1 ^ L_var2) & MIN_32) != 0)
{
if ((L_var_out ^ L_var1) & MIN_32)
{
L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;
//printf("LsubÒç³ö\n");
}
}
return (L_var_out);
}
inline Word32 L_add_half(Word32 L_var1, Word32 L_var2)
{
return (L_add(L_var1, L_var2)) >> 1;
}
inline Word32 L_sub_half(Word32 L_var1, Word32 L_var2)
{
return (L_sub(L_var1, L_var2)) >> 1;
}
inline Word16 abs16(Word16 x)
{
if (x < 0)
{
if (x == MIN_16)
{
return MAX_16;
}
else
{
return -x;
}
}
else
{
return x;
}
}
inline Word32 abs32(Word32 x)
{
if (x < 0)
{
if (x == MIN_32)
{
return MAX_32;
}
else
{
return -x;
}
}
else
{
return x;
}
}
inline Word16 convert_q31_q15_u(Word32 x)
{
return (x + 0x8000) >> 16;
}
inline Word32 L_mult(Word16 var1, Word16 var2)
{
Word32 L_var_out;
L_var_out = (Word32)var1 * (Word32)var2;
if (L_var_out != (Word32)0x40000000L)
{
L_var_out *= 2;
}
else
{
L_var_out = 0x7fffffffL;
}
return (L_var_out);
}
inline Word32 L_mac(Word32 L_var3, Word16 var1, Word16 var2)
{
Word32 L_var_out;
Word32 L_product;
L_product = L_mult(var1, var2);
L_var_out = L_add(L_var3, L_product);
return (L_var_out);
}
inline Word32 L_msu(Word32 L_var3, Word16 var1, Word16 var2)
{
Word32 L_var_out;
Word32 L_product;
L_product = L_mult(var1, var2);
L_var_out = (L_var3 - L_product);
return (L_var_out);
}
/* Multiply var1 by var2 and shift the result left by 1. Add the 32 bit
result to L_var3 with saturation. Round the LS 16 bits of the result
into the MS 16 bits with saturation and shift the result right by 16. */
inline Word16 mac_r(Word32 L_var3, Word16 var1, Word16 var2)
{
Word16 var_out;
L_var3 = L_mac(L_var3, var1, var2);
L_var3 = L_add(L_var3, (Word32)0x00008000L);
var_out = (L_var3) >> 16;
return (var_out);
}
inline Word16 msu_r(Word32 L_var3, Word16 var1, Word16 var2)
{
Word16 var_out;
L_var3 = L_msu(L_var3, var1, var2);
L_var3 = L_add(L_var3, (Word32)0x00008000L);
var_out = (L_var3) >> 16;
return (var_out);
}
#endif
/* below functions needs to be further optimized */
inline Word32 L_negate(Word32 L_var1)
{
Word32 L_var_out;
L_var_out = (L_var1 == MIN_32) ? MAX_32 : -L_var1;
return (L_var_out);
}
inline UWord32 sll32(UWord32 a, UWord32 b)
{
return a << b;
}
inline Word16 saturate(Word32 vin)
{
Word16 vout;
if (vin > MAX_16) {
vout = MAX_16;
}
else if (vin < MIN_16) {
vout = MIN_16;
}
else {
vout = (Word16)vin;
}
return vout;
}
inline Word16 add_s_16(Word16 vin1, Word16 vin2)
{
Word16 vout;
Word32 tmp;
tmp = (Word32)vin1 + (Word32)vin2;
vout = saturate(tmp);
return (vout);
}
inline Word16 sub_s_16(Word16 vin1, Word16 vin2)
{
Word16 vout;
Word32 tmp;
tmp = (Word32)vin1 - (Word32)vin2;
vout = saturate(tmp);
return (vout);
}
inline Word16 mult_16_shift(Word16 vin1, Word16 vin2, Word32 shift)
{
Word32 tmp;
Word16 vout;
tmp = (Word32)vin1 * (Word32)vin2 >> shift;
vout = saturate(tmp);
return vout;
}
inline Word16 mult_r_16_shift(Word16 vin1, Word16 vin2, Word32 shift)
{
Word32 tmp;
Word32 round_factor;
Word16 vout;
round_factor = 1 << (shift - 1);
tmp = (Word32)vin1 * (Word32)vin2;
tmp = (tmp + round_factor) >> shift;
vout = saturate(tmp);
return vout;
}
inline Word32 mult_32_shift(Word32 vin1, Word32 vin2, Word32 shift)
{
Word64 tmp;
Word32 vout;
tmp = (Word64)vin1 * (Word64)vin2;
vout = (Word32)(tmp >> shift);
return vout;
}
inline Word16 asr_r_16(Word16 vin, Word32 shift)
{
Word16 vout;
Word32 round_factor = 1 << (shift - 1);
vout = (vin + round_factor) >> shift;
return vout;
}
inline Word32 asr_r_32(Word32 vin, Word32 shift)
{
Word32 vout;
Word32 round_factor = 1 << (shift - 1);
vout = (vin + round_factor) >> shift;
return vout;
}
inline Word16 norm32_l(Word32 x)
{
if (x==0)
{
return 0;
}
else
{
return (Word16)clrs32(x);
}
}
inline Word64 mac_32_32_64(Word32 vin1, Word32 vin2, Word64 vout)
{
vout = vout + (Word64)vin1 * (Word64)vin1;
if (vout >= 0x80000000)
{
vout = 0x7FFFFFF;
}
return vout;
}
inline Word16 norm16_l(Word16 x)
{
if (x == 0)
{
return 0;
}
else
{
return clrs16(x);
}
}
inline Word16 negate(Word16 var1)
{
Word16 var_out;
var_out = (var1 == MIN_16) ? MAX_16 : -var1;
return (var_out);
}
inline Word16 lshr(Word16 var1, Word16 var2) {
Word16 var_out;
var_out = var1 >> 1;
var_out = var_out & 0x7fff;
var_out = var_out >> (var2 - 1);
//printf("\noutput=%d %d\n", (Word16)__nds__srl16(var1, var2), var_out);
return (var_out);
}
#define cplxMult32_16_32(r, i, a, b, c, d) \
do \
{ \
r =(( ( (mult_32_16_32(a, c)) ) - ( (mult_32_16_32(b, d)) ) )); \
i =(( ( (mult_32_16_32(a, d)) ) + ( (mult_32_16_32(b, c)) ) )); \
} while (0)
#endif //#if (ALG_LC3_ENABLE)
#endif
+16
View File
@@ -0,0 +1,16 @@
#ifndef _LTPF_DECODER_H
#define _LTPF_DECODER_H
#include "../inc/lc3_dec.h"
#if (ALG_LC3_ENABLE)
#ifdef FIXED_POINT
LC3DEC_Error dec_ltpf_fix(LC3_DEC_STRU* dec, Word32* x, Word32 nbits, Word32* x_ltpf);
#else
LC3DEC_Error dec_ltpf(LC3_DEC_STRU* dec, double* x, Word32 nbits, double* x_ltpf);
#endif
#endif //#if (ALG_LC3_ENABLE)
#endif
+16
View File
@@ -0,0 +1,16 @@
#ifndef _MDCT_DECODER_H
#define _MDCT_DECODER_H
#include "../inc/lc3_dec.h"
#if (ALG_LC3_ENABLE)
#ifdef FIXED_POINT
LC3DEC_Error dec_imdct_fix(LC3_DEC_STRU* dec, Word32* in, Word32* out, Word16* exp);
#else
LC3DEC_Error dec_imdct(LC3_DEC_STRU* dec, double* in, double* out);
#endif
#endif
#endif
+18
View File
@@ -0,0 +1,18 @@
#ifndef _NOISE_FILLING_H
#define _NOISE_FILLING_H
#include "../inc/lc3_dec.h"
#if (ALG_LC3_ENABLE)
#ifdef FIXED_POINT
#define NOISEFILLING_Q (15)
LC3DEC_Error dec_noisefilling_fix(LC3_DEC_STRU* dec, Word32* Xq);
#else
LC3DEC_Error dec_noisefilling(LC3_DEC_STRU* dec, double* Xq);
#endif
#endif //#if (ALG_LC3_ENABLE)
#endif
+18
View File
@@ -0,0 +1,18 @@
#ifndef _RESIDUAL_DECODER_H
#define _RESIDUAL_DECODER_H
#include "../inc/lc3_dec.h"
#if (ALG_LC3_ENABLE)
#define RESIDUAL_Q (15)
#define RESIDUAL_A (3 << (RESIDUAL_Q - 4)) // 0.1875
#define RESIDUAL_B (5 << (RESIDUAL_Q - 4)) // 0.3125
LC3DEC_Error dec_residual_fix(Word16* X_q, Word16 N_E, Word16* resBits, Word16* nResBits, Word32* X_q_residual);
LC3DEC_Error dec_residual(Word16* X_q, Word16 N_E, Word16* resBits, Word16* nResBits, double* X_q_residual);
#endif //#if (ALG_LC3_ENABLE)
#endif
+15
View File
@@ -0,0 +1,15 @@
#ifndef _SNS_DECODER_H
#define _SNS_DECODER_H
#include "../inc/lc3_dec.h"
#if (ALG_LC3_ENABLE)
#ifdef FIXED_POINT
LC3DEC_Error dec_sns_fix(LC3_DEC_STRU* dec, Word32* X_s, Word32* X);
#else
LC3DEC_Error dec_sns(LC3_DEC_STRU* dec, double* X_s, double* X);
#endif
#endif //#if (ALG_LC3_ENABLE)
#endif
+15
View File
@@ -0,0 +1,15 @@
#ifndef _TNS_DECODER_H
#define _TNS_DECODER_H
#include "../inc/lc3_dec.h"
#if (ALG_LC3_ENABLE)
#ifdef FIXED_POINT
LC3DEC_Error dec_tns_fix(LC3_DEC_STRU* dec, Word32* Xq);
#else
LC3DEC_Error dec_tns(LC3_DEC_STRU* dec, double* Xq);
#endif
#endif //#if (ALG_LC3_ENABLE)
#endif
+284
View File
@@ -0,0 +1,284 @@
/********************************************************************************************************
* @file usbaud.c
*
* @brief This is the source file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#include "drivers.h"
#include "usbaud.h"
#include "application/usbstd/usb.h"
#include "application/usbstd/AudioClassCommon.h"
#include "application/rf_frame.h"
/*************************************************
* g_audio_hid_chg:
* 0x00: no event
* 0x01: speaker volume change
* 0x02: speaker mute change
* 0x11: microphone volume change
* 0x12: microphone mute change
*************************************************/
static speaker_setting_t speaker_setting;
static mic_setting_t mic_setting;
void usbaud_set_audio_mode(int iso_en, int mono_en) {
SET_FLD(reg_usb_ep_ctrl(USB_EDP_MIC), FLD_USB_EP_EOF_ISO | FLD_USB_EP_MONO);
}
#if 0
void usbaud_hid_report(char format, char volume) {
unsigned char sAudioHidReport[] = { 0x01,/* report ID */
format,/*[0]:play/pause,
[1]:scan next track,
[2]:scan previous track,
[3]:stop,
[4]:play,
[5]:pause,
[6]:fast forward,
[7]:rewind,
*/
volume /*[0]:volume up
[1]:volume down
[2]:mute
[3:7] 0;
*/
};
WriteEndPoint(EDP_ID_AUDIO_HID, sAudioHidReport, sizeof(sAudioHidReport));
}
#endif
#if(USB_SPEAKER_ENABLE || USB_MIC_ENABLE) // use for volumn control, mute, next, prev track, move to mouse hid
int usbaud_hid_report(u8 cmd, u8 vol){
if (usbhw_is_ep_busy(USB_EDP_AUDIO_IN))
return 0;
reg_usb_ep_ptr(USB_EDP_AUDIO_IN) = 0;
// please refer to keyboard_report_desc
reg_usb_ep_dat(USB_EDP_AUDIO_IN) = USB_HID_AUDIO;
reg_usb_ep_dat(USB_EDP_AUDIO_IN) = cmd;
reg_usb_ep_dat(USB_EDP_AUDIO_IN) = vol;
reg_usb_ep_ctrl(USB_EDP_AUDIO_IN) = FLD_EP_DAT_ACK; // ACK
return 1;
}
#endif
#if 0
u8 usbaud_handle_report(u8 c) {
if (USB_REPORT_NO_EVENT == c) {
return USB_REPORT_NO_EVENT;
}
if(reg_usb_ep_ctrl(USB_EDP_AUDIO) & FLD_USB_EP_BUSY)
return c;
if(USB_REPORT_RELEASE == c){
usbaud_hid_report(0, 0);
return USB_REPORT_NO_EVENT;
}else{
usbaud_hid_report((c < 0x10) ? (1 << c) : 0
,(c < 0x10) ? 0 : (1 << (c & 0x0f)));
return USB_REPORT_RELEASE;
}
}
#endif
static u16 usbaud_cal_speaker_step(s16 vol){
if(vol < SPEAKER_VOL_MIN)
return 0;
return (vol - SPEAKER_VOL_MIN) / SPEAKER_VOL_RES;
}
static u16 usbaud_cal_mic_step(s16 vol){
if(vol < MIC_VOL_MIN)
return 0;
return (vol - MIC_VOL_MIN) / MIC_VOL_RES;
}
void usbaud_set_speaker_vol(s16 vol){
speaker_setting.vol_cur = vol;
speaker_setting.vol_step = usbaud_cal_speaker_step(vol);
}
void usbaud_set_mic_vol(s16 vol){
mic_setting.vol_cur = vol;
mic_setting.vol_step = usbaud_cal_mic_step(vol);
}
usb_audio_status_t g_usb_audio_status;
u8 usbaud_speaker_vol_get(void){
//return ((g_usb_audio_status.speaker_mute << 7) | g_usb_audio_status.speaker_vol);
return (speaker_setting.mute << 7) | (speaker_setting.vol_step & 0x7f);
}
u8 usbaud_mic_vol_get(void){
//return ((g_usb_audio_status.speaker_mute << 7) | g_usb_audio_status.speaker_vol);
return (mic_setting.mute << 7) | (mic_setting.vol_step & 0x7f);
}
void usbaud_mic_en(int en) {
mic_setting.mute = en;
}
volatile int aaa_audio_intf_set = 0;
int usb_audio_class_out_intf_proc(u8 type, u8 feature_id){
int ret = 0;
usb_audio_status_t *p_aud = &g_usb_audio_status;
aaa_audio_intf_set = 0;
aaa_audio_intf_set = (type << 8);
aaa_audio_intf_set |= feature_id;
switch (type) {
// mute control and sample
case 0x01:
switch (feature_id) {
case 0x00://set sample frequency
break;
case AUDIO_FEATURE_ID_SPEAKER:// Feature ID 0x02, Speaker
p_aud->speaker_mute = usbhw_read_ctrl_ep_data();
p_aud->change |= 0x1;
break;
case AUDIO_FEATURE_ID_MIC:// Feature ID 0x05, MIC
p_aud->mic_mute = usbhw_read_ctrl_ep_data();
p_aud->change |= 0x2;
break;
default:
ret = 1;
break;
}
break;
// volume control
case 0x02:
switch (feature_id) {
case AUDIO_FEATURE_ID_SPEAKER: // Feature ID 0x02, Speaker
p_aud->speaker_vol = usbhw_read_ctrl_ep_data() + (usbhw_read_ctrl_ep_data() << 8);
p_aud->speaker_vol = ((p_aud->speaker_vol - (short)SPEAKER_VOL_MIN + SPEAKER_VOL_STEP) * (10 - 1)) >> 12;
if (p_aud->speaker_vol < 0){
p_aud->speaker_vol = 0;
}
p_aud->change |= 0x4;
break;
case AUDIO_FEATURE_ID_MIC: // Feature ID 0x05, MIC
p_aud->mic_vol = usbhw_read_ctrl_ep_data() + (usbhw_read_ctrl_ep_data() << 8);
p_aud->change |= 0x8;
break;
default:
ret = 1;
break;
}
default:
break;
}
return ret;
}
// return -1 on fail, 0 on success
int usbaud_handle_set_speaker_cmd(int type) {
if(type == AUDIO_FEATURE_MUTE){
speaker_setting.mute = usbhw_read_ctrl_ep_data();
}else if(type == AUDIO_FEATURE_VOLUME){
u16 val = usbhw_read_ctrl_ep_u16();
usbaud_set_speaker_vol(val);
}else{
return -1;
}
return 0;
}
// return -1 on fail, 0 on success
int usbaud_handle_set_mic_cmd(int type) {
if(type == AUDIO_FEATURE_MUTE){
mic_setting.mute = usbhw_read_ctrl_ep_data();
}else if(type == AUDIO_FEATURE_VOLUME){
u16 val = usbhw_read_ctrl_ep_u16();
usbaud_set_mic_vol(val);
}else{
}
return 0;
}
// return -1 on fail, 0 on success
int usbaud_handle_get_speaker_cmd(int req, int type) {
if(type == AUDIO_FEATURE_MUTE){
usbhw_write_ctrl_ep_data(speaker_setting.mute);
}else if(type == AUDIO_FEATURE_VOLUME){
switch (req) {
case AUDIO_REQ_GetCurrent:
usbhw_write_ctrl_ep_u16(speaker_setting.vol_cur);
break;
case AUDIO_REQ_GetMinimum:
usbhw_write_ctrl_ep_u16(SPEAKER_VOL_MIN);
break;
case AUDIO_REQ_GetMaximum:
usbhw_write_ctrl_ep_u16(SPEAKER_VOL_MAX);
break;
case AUDIO_REQ_GetResolution:
usbhw_write_ctrl_ep_u16(SPEAKER_VOL_RES);
break;
default:
return -1;
}
}else{
return -1;
}
return 0;
}
// return -1 on fail, 0 on success
int usbaud_handle_get_mic_cmd(int req, int type) {
if(type == AUDIO_FEATURE_MUTE){
usbhw_write_ctrl_ep_data(mic_setting.mute);
}else if(type == AUDIO_FEATURE_VOLUME){
switch (req) {
case AUDIO_REQ_GetCurrent:
usbhw_write_ctrl_ep_u16(mic_setting.vol_cur);
break;
case AUDIO_REQ_GetMinimum:
usbhw_write_ctrl_ep_u16(MIC_VOL_MIN);
break;
case AUDIO_REQ_GetMaximum:
usbhw_write_ctrl_ep_u16(MIC_VOL_MAX);
break;
case AUDIO_REQ_GetResolution:
usbhw_write_ctrl_ep_u16(MIC_VOL_RES);
break;
default:
return -1;
}
}else{
return -1;
}
return 0;
}
void usbaud_init(void) {
if (USB_MIC_ENABLE && 1 == MIC_CHANNEL_COUNT) {
usbaud_set_audio_mode(1, 1);
}
#if (USB_SPEAKER_ENABLE)
usbaud_set_speaker_vol(SPEAKER_VOL_MAX);
#endif
#if (USB_MIC_ENABLE)
mic_setting.vol_cur = MIC_VOL_DEF;
#endif
}
+100
View File
@@ -0,0 +1,100 @@
/********************************************************************************************************
* @file usbaud.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include <application/usbstd/HIDClassCommon.h>
#include <application/usbstd/HIDReportData.h>
#include "tl_common.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
// telink usb report ctrl command. used mixed with USB_REPORT_NO_EVENT
enum {
USB_AUD_PLAY_PAUSE = 0,
USB_AUD_NEXT_TRACK = 1,
USB_AUD_PREV_TRACK = 2,
USB_AUD_STOP = 3,
USB_AUD_PLAY = 4,
USB_AUD_PAUSE = 5,
USB_AUD_FAST_FWD = 6,
USB_AUD_REWIND = 7,
USB_AUD_VOL_INC = 0x10,
USB_AUD_VOL_DEC = 0x11,
USB_AUD_VOL_MUTE = 0x12,
};
#define AUDIO_FEATURE_ID_SPEAKER 0x02
#define AUDIO_FEATURE_ID_MIC 0x05
typedef struct{
s16 speaker_vol;
s16 mic_vol;
s8 speaker_mute;
s8 mic_mute;
s8 change;
}usb_audio_status_t;
typedef struct {
u16 vol_cur;
u16 vol_step;
u8 mute;
}speaker_setting_t;
typedef struct {
u16 vol_cur;
u16 vol_step;
u8 mute;
}mic_setting_t;
#define AUDIO_VOLUME_STEP_MAX 11
#define MIC_VOL_MIN ((s16) 0x0000) /* Volume Minimum Value */
#define MIC_VOL_MAX ((s16) 0x1e00) /* Volume Maximum Value */
#define MIC_VOL_RES 0x0180 /* Volume Resolution */
#define MIC_VOL_DEF 0x1800 /* Volume default */
#define MIC_MAX_STEP (MIC_VOL_MAX / MIC_VOL_RES)
#define SPEAKER_VOL_MIN ((s16) 0xa000) /* Volume Minimum Value */
#define SPEAKER_VOL_MAX ((s16) 0x0300) /* Volume Maximum Value */
#define SPEAKER_VOL_RES 0x0180 /* Volume Resolution */
#define SPEAKER_VOL_DEF 0x8000 /* Volume default */
#define SPEAKER_VOL_STEP 400
int usbaud_handle_set_speaker_cmd(int type);
int usbaud_handle_set_mic_cmd(int type);
int usbaud_handle_get_speaker_cmd(int req, int type);
int usbaud_handle_get_mic_cmd(int req, int type);
void usbaud_init(void);
u8 usbaud_speaker_vol_get(void);
u8 usbaud_mic_vol_get(void);
void usbaud_mic_en(int en);
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+115
View File
@@ -0,0 +1,115 @@
/********************************************************************************************************
* @file usbaud_i.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include "drivers.h"
#include "usbaud.h"
#include "application/usbstd/AudioClassCommon.h"
#include "application/usbstd/usb.h"
#if 0
static const USB_Descriptor_HIDReport_Datatype_t usbaud_report_desc[] = {
HID_RI_USAGE_PAGE(8, 0x0c), /* Consumer Page */
HID_RI_USAGE(8, 0x01) , /* Consumer Controls */
HID_RI_COLLECTION(8, 0x01) , /* Application */
HID_RI_REPORT_ID(8, 0x01) , /*Report ID*/
HID_RI_LOGICAL_MINIMUM(8, 0x00) ,
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
HID_RI_USAGE(8, 0xcd), /* Play/Pause (toggle) */
HID_RI_USAGE(8, 0xb5) , /* Next Track */
HID_RI_USAGE(8, 0xb6) , /* Previous Track */
HID_RI_USAGE(8, 0xb7) , /* Stop */
HID_RI_REPORT_SIZE(8, 0x01) ,
HID_RI_REPORT_COUNT(8, 0x04),
HID_RI_INPUT(8, HID_IOF_VARIABLE),
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
HID_RI_USAGE(8, 0xb0), /* Play */
HID_RI_USAGE(8, 0xb1) , /* Pause */
HID_RI_USAGE(8, 0xb3) , /* Fast Forward */
HID_RI_USAGE(8, 0xb4) , /* Rewind */
HID_RI_REPORT_SIZE(8, 0x01) ,
HID_RI_REPORT_COUNT(8, 0x04),
HID_RI_INPUT(8, HID_IOF_NO_PREFERRED_STATE | HID_IOF_VARIABLE),
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
HID_RI_USAGE(8, 0xe9),
HID_RI_USAGE(8, 0xea),
HID_RI_USAGE(8, 0xe2),
HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_REPORT_COUNT(8, 0x03),
HID_RI_INPUT(8, HID_IOF_NO_PREFERRED_STATE | HID_IOF_VARIABLE),
HID_RI_REPORT_SIZE(8, 0x05),
HID_RI_REPORT_COUNT(8, 0x01),
HID_RI_INPUT(8, HID_IOF_CONSTANT),
HID_RI_END_COLLECTION(0),
HID_RI_USAGE_PAGE(16, 0xffa0),
HID_RI_USAGE(8, 0x01),
HID_RI_COLLECTION(8, 0x01), /* Application */
HID_RI_REPORT_ID(8, 0x02) , /*Report ID*/
HID_RI_USAGE(8, 0x01) ,
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(16, 0x00ff),
HID_RI_REPORT_SIZE(8, 0x08),
HID_RI_REPORT_COUNT(8, 0x02),
HID_RI_OUTPUT(8, HID_IOF_DATA),
HID_RI_USAGE(8, 0x02), /* mouse? */
HID_RI_REPORT_SIZE(8, 0x08) ,
HID_RI_REPORT_COUNT(8, 0x02),
HID_RI_INPUT(8, HID_IOF_DATA),
HID_RI_END_COLLECTION(0), };
#endif
//Definition of USB HID report descriptor
static const USB_Descriptor_HIDReport_Datatype_t usbaud_report_desc[] = {
0x05, 0x0c, 0x09, 0x01, 0xa1, 0x01,
0x85, 0x01, 0x15, 0x00, 0x25, 0x01, 0x09, 0xcd, 0x09, 0xb5, 0x09, 0xb6,
0x09, 0xb7, 0x75, 0x01, 0x95, 0x04, 0x81, 0x02, 0x15, 0x00, 0x25, 0x01,
0x09, 0xb0, 0x09, 0xb1, 0x09, 0xb3, 0x09, 0xb4, 0x75, 0x01, 0x95, 0x04,
0x81, 0x22, 0x15, 0x00, 0x25, 0x01, 0x09, 0xe9, 0x09, 0xea, 0x09, 0xe2,
0x75, 0x01, 0x95, 0x03, 0x81, 0x22, 0x75, 0x05, 0x95, 0x01, 0x81, 0x01,
0xc0, 0x06, 0xa0, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x02, 0x09, 0x01,
0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x02, 0x91, 0x00, 0x09,
0x02, 0x75, 0x08, 0x95, 0x02, 0x81, 0x00, 0xc0, };
static inline u8* usbaud_get_report_desc(void) {
return (u8*) (usbaud_report_desc);
}
static inline u16 usbaud_get_report_desc_size(void) {
return sizeof(usbaud_report_desc);
}
+321
View File
@@ -0,0 +1,321 @@
/********************************************************************************************************
* @file usbcdc.c
*
* @brief This is the source file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#if(USB_CDC_ENABLE)
#include "usbcdc.h"
#include "application/usbstd/usb.h"
#include "application/rf_frame.h"
void usbcdc_write32(u32 value);
void usbcdc_read32(u32* value);
int usbcdc_recvTimeoutCb(void* arg);
typedef struct {
u8 *rxBuf;
u8 *txBuf;
/* Following variables are used in the RX more than CDC_TXRX_EPSIZE */
ev_time_event_t timer;
u8 lastIndex;
u16 lenToSend;
u16 lastSendIndex;
cdc_handlerFn_t rxCb;
cdc_handlerFn_t txCb;
} cdc_ctrl_t;
#ifdef STATIC_V_INST
cdc_ctrl_t cdc_vs;
#endif
cdc_ctrl_t *cdc_v;
USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
{
//.Config =
{
0, //ControlInterfaceNumber
CDC_TX_EPNUM, // DataINEndpointNumber
CDC_TXRX_EPSIZE, // DataINEndpointSize
false, // DataINEndpointDoubleBank
CDC_RX_EPNUM, // DataOUTEndpointNumber
CDC_TXRX_EPSIZE, // DataOUTEndpointSize
false, // DataOUTEndpointDoubleBank
CDC_NOTIFICATION_EPNUM, // NotificationEndpointNumber
CDC_NOTIFICATION_EPSIZE, // NotificationEndpointSize
false, // NotificationEndpointDoubleBank
},
};
USB_ClassInfo_CDC_Device_t *CDCInterfaceInfo = &VirtualSerial_CDC_Interface;
void CDC_Device_ProcessControlRequest(u8 bRequest, u16 wValue, u16 wIndex, u16 wLength)
{
if (wIndex != CDCInterfaceInfo->Config.ControlInterfaceNumber)
return;
switch (bRequest)
{
case CDC_REQ_GetLineEncoding:
usbcdc_write32(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS);
usbhw_write_ctrl_ep_data(CDCInterfaceInfo->State.LineEncoding.CharFormat);
usbhw_write_ctrl_ep_data(CDCInterfaceInfo->State.LineEncoding.ParityType);
usbhw_write_ctrl_ep_data(CDCInterfaceInfo->State.LineEncoding.DataBits);
break;
case CDC_REQ_SetLineEncoding:
usbcdc_read32(&CDCInterfaceInfo->State.LineEncoding.BaudRateBPS);
CDCInterfaceInfo->State.LineEncoding.CharFormat = usbhw_read_ctrl_ep_data();
CDCInterfaceInfo->State.LineEncoding.ParityType = usbhw_read_ctrl_ep_data();
CDCInterfaceInfo->State.LineEncoding.DataBits = usbhw_read_ctrl_ep_data();
//EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo);
break;
case CDC_REQ_SetControlLineState:
CDCInterfaceInfo->State.ControlLineStates.HostToDevice = wValue;
//EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo);
break;
case CDC_REQ_SendBreak:
break;
}
}
void usbcdc_write32(u32 value)
{
usbhw_write_ctrl_ep_data(value&0xff);
usbhw_write_ctrl_ep_data((value>>8)&0xff);
usbhw_write_ctrl_ep_data((value>>16)&0xff);
usbhw_write_ctrl_ep_data((value>>24)&0xff);
}
void usbcdc_read32(u32* value)
{
u32 temp = 0;
*value = usbhw_read_ctrl_ep_data();
temp = usbhw_read_ctrl_ep_data();
*value = (temp << 8) | (*value);
temp = 0;
temp = usbhw_read_ctrl_ep_data();
*value = (temp << 16) | (*value);
temp = 0;
temp = usbhw_read_ctrl_ep_data();
*value = (temp << 24) | (*value);
}
void usbcdc_init(void)
{
/* Init UART parameters */
CDCInterfaceInfo->State.LineEncoding.BaudRateBPS = 115200;
CDCInterfaceInfo->State.LineEncoding.CharFormat = 0;
CDCInterfaceInfo->State.LineEncoding.ParityType = 0;
CDCInterfaceInfo->State.LineEncoding.DataBits = 8;
cdc_v = &cdc_vs;
cdc_v->lastIndex = 0;
cdc_v->timer.cb = usbcdc_recvTimeoutCb;
}
void usbcdc_setRxBuf(u8 *buf)
{
cdc_v->rxBuf = buf;
}
void usbcdc_setCB(cdc_handlerFn_t rxFunc, cdc_handlerFn_t txCb)
{
cdc_v->rxCb = rxFunc;
cdc_v->txCb = txCb;
}
int usbcdc_recvTimeoutCb(void* arg)
{
u8* p;
cdc_v->lastIndex = 0;
/* Clear the buffer */
p = cdc_v->rxBuf;
cdc_v->rxBuf = NULL;
/* Callback */
if (cdc_v->rxCb) {
cdc_v->rxCb(p);
}
return -1;
}
void usbcdc_recvData(void)
{
u8 i;
u8 *p;
u8 len;
u8 fEnd = 0;
/* No buffer */
if (!cdc_v->rxBuf) {
while(1);
}
if (!is_timer_expired(&cdc_v->timer)) {
ev_unon_timer(&cdc_v->timer);
}
len = reg_usb_ep_ptr(CDC_RX_EPNUM & 0x07);
fEnd = (len == CDC_TXRX_EPSIZE) ? 0 : 1;
usbhw_reset_ep_ptr(CDC_RX_EPNUM);
for (i = 0; i < len; i++) {
cdc_v->rxBuf[cdc_v->lastIndex++] = usbhw_read_ep_data(CDC_RX_EPNUM);
}
if (fEnd) {
cdc_v->lastIndex = 0;
/* Clear the buffer */
p = cdc_v->rxBuf;
cdc_v->rxBuf = NULL;
/* Callback */
if (cdc_v->rxCb) {
cdc_v->rxCb(p);
}
} else {
ev_on_timer(&cdc_v->timer, 500);
}
}
u8 T_BUF[60];
u32 T_CNT;
u8 usbcdc_sendBulkData(void)
{
u16 len;
/* Wait until not busy */
if (usbhw_is_ep_busy(CDC_TX_EPNUM)) {
/* Return to wait IRQ come again */
return 0;
}
/* Get the length to send in this bulk transaction */
len = (cdc_v->lenToSend > CDC_TXRX_EPSIZE) ? CDC_TXRX_EPSIZE : cdc_v->lenToSend;
cdc_v->lenToSend -= len;
if (len == 0) {
return 0;
}
reg_usb_ep_ptr(CDC_TX_EPNUM) = 0;
/* Write data to USB fifo */
foreach (i, len) {
T_BUF[i] = cdc_v->txBuf[cdc_v->lastSendIndex];
reg_usb_ep_dat(CDC_TX_EPNUM) = cdc_v->txBuf[cdc_v->lastSendIndex++];
}
/* Write ACK */
reg_usb_ep_ctrl(CDC_TX_EPNUM) = FLD_EP_DAT_ACK; // ACK
u16 t = 0;
while(usbhw_is_ep_busy(CDC_TX_EPNUM)) {
if (t++ > 10000) {
T_CNT++;
reg_usb_ep_ctrl(CDC_TX_EPNUM) &= 0xfe; // clear bit(0)
}
};
/* TX transaction finish */
if (cdc_v->lenToSend == 0) {
cdc_v->lenToSend = 0;
cdc_v->lastSendIndex = 0;
if (cdc_v->txCb) {
EV_SCHEDULE_TASK(cdc_v->txCb, cdc_v->txBuf);
}
cdc_v->txBuf = NULL;
}
return len;
}
usbcdc_sts_t usbcdc_sendData(u8 *buf, u8 len)
{
if (cdc_v->txBuf) {
return USB_BUSY;
}
/* Init the bulk transfer */
cdc_v->lenToSend = len;
cdc_v->txBuf = buf;
cdc_v->lastSendIndex = 0;
/* Send first bulk */
usbcdc_sendBulkData();
usbhw_data_ep_ack(USB_EDP_CDC_OUT);
return SUCCESS;
}
u8 usbcdc_isAvailable(void)
{
return (cdc_v->txBuf == NULL);
}
#endif /* USB_CDC_ENABLE */
+70
View File
@@ -0,0 +1,70 @@
/********************************************************************************************************
* @file usbcdc.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include "application/usbstd/CDCClassCommon.h"
#include "application/usbstd/CDCClassDevice.h"
#include "common/types.h"
#include "common/bit.h"
#include "tl_common.h"
#include "drivers.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
typedef void ( *cdc_handlerFn_t)( u8* pData);
typedef struct {
u8 len;
u8 data[1];
} usbcdc_txBuf_t;
typedef enum usbcdc_sts_e {
// success = 0
USB_BUSY = 1,
USB_MULTIBLOCK,
} usbcdc_sts_t;
void CDC_Device_ProcessControlRequest(u8 bRequest, u16 wValue, u16 wIndex, u16 wLength);
usbcdc_sts_t usbcdc_sendData(u8* buf, u8 len);
u8 usbcdc_sendBulkData(void);
u8 usbcdc_isAvailable(void);
u8* usbcdc_getData(void);
void usbcdc_init(void);
void usbcdc_setCB(cdc_handlerFn_t rxFunc, cdc_handlerFn_t txCb);
void usbcdc_setRxBuf(u8 *buf);
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+30
View File
@@ -0,0 +1,30 @@
/********************************************************************************************************
* @file usbcdc_i.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include "usbcdc.h"
#include "drivers.h"
#include "application/usbstd/usb.h"
+366
View File
@@ -0,0 +1,366 @@
/********************************************************************************************************
* @file usbkb.c
*
* @brief This is the source file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#include "usbkb.h"
#include "usbmouse.h"
#include "application/usbstd/usb.h"
#include "application/usbstd/usbkeycode.h"
#include "application/rf_frame.h"
u8 usb_fifo[USB_FIFO_NUM][USB_FIFO_SIZE];
u8 usb_ff_rptr = 0;
u8 usb_ff_wptr = 0;
int usbkb_hid_report_normal(u8 ctrl_key, u8 *keycode);
static u8 vk_sys_map[VK_SYS_CNT] = {
VK_POWER_V, VK_SLEEP_V, VK_WAKEUP_V
};
static vk_ext_t vk_media_map[VK_MEDIA_CNT] = {
{VK_W_SRCH_V},
{VK_HOME_V},
{VK_W_BACK_V},
{VK_W_FORWRD_V},
{VK_W_STOP_V},
{VK_W_REFRESH_V},
{VK_W_FAV_V},
{VK_MEDIA_V},
{VK_MAIL_V},
{VK_CAL_V},
{VK_MY_COMP_V},
{VK_NEXT_TRK_V},
{VK_PREV_TRK_V},
{VK_STOP_V},
{VK_PLAY_PAUSE_V},
{VK_W_MUTE_V},
{VK_VOL_UP_V},
{VK_VOL_DN_V},
};
enum{
KB_NORMAL_RELEASE_MASK = BIT(0),
KB_SYS_RELEASE_MASK = BIT(1),
KB_MEDIA_RELEASE_MASK = BIT(2),
};
#define USBKB_BUFF_DATA_NUM 8
//static
kb_data_t kb_dat_buff[USBKB_BUFF_DATA_NUM];
//static
u8 usbkb_wptr, usbkb_rptr;
static u32 usbkb_not_released;
static u32 usbkb_data_report_time;
void usbkb_report_frame(void)
{
if(usbkb_wptr != usbkb_rptr){
kb_data_t *data = (kb_data_t *)(&kb_dat_buff[usbkb_rptr]);
usbkb_hid_report(data);
BOUND_INC_POW2(usbkb_rptr,USBKB_BUFF_DATA_NUM);
}
return;
}
static void usbkb_release_normal_key(void){
if(usbkb_not_released & KB_NORMAL_RELEASE_MASK){
u8 normal_keycode[KEYBOARD_REPORT_KEY_MAX] = {0};
if(usbkb_hid_report_normal(0, normal_keycode)){
BM_CLR(usbkb_not_released, KB_NORMAL_RELEASE_MASK);
}
}
}
static void usbkb_release_sys_key(void){
if(usbkb_not_released & KB_SYS_RELEASE_MASK){
u32 release_data = 0;
if(usbmouse_hid_report(USB_HID_KB_SYS, (u8*)(&release_data), 1)){
BM_CLR(usbkb_not_released, KB_SYS_RELEASE_MASK);
}
}
}
static void usbkb_release_media_key(void){
if(usbkb_not_released & KB_MEDIA_RELEASE_MASK){
u8 ext_keycode[MOUSE_REPORT_DATA_LEN] = {0};
if(usbmouse_hid_report(USB_HID_KB_MEDIA, ext_keycode, MEDIA_REPORT_DATA_LEN)){
BM_CLR(usbkb_not_released, KB_MEDIA_RELEASE_MASK);
}
}
}
static void usbkb_release_keys(void){
usbkb_release_sys_key();
usbkb_release_normal_key();
usbkb_release_media_key();
}
void usbkb_release_check(){
if(usbkb_not_released && clock_time_exceed(usbkb_data_report_time, USB_KEYBOARD_RELEASE_TIMEOUT)){
usbkb_release_keys(); // release keys
}
}
int usbkb_separate_key_types(u8 *keycode, u8 cnt, u8 *normal_key, u8 *ext_key){
int normal_cnt = 0;
foreach(i, cnt){
if(keycode[i] >= VK_EXT_START && keycode[i] < VK_EXT_END){
*ext_key = keycode[i];
}else{
normal_key[normal_cnt++] = keycode[i];
}
}
return normal_cnt;
}
int usbkb_hid_report_normal(u8 ctrl_key, u8 *keycode){
if(usbhw_is_ep_busy(USB_EDP_KEYBOARD_IN)){
u8 *pData = (u8 *)&usb_fifo[usb_ff_wptr++ & (USB_FIFO_NUM - 1)];
pData[0] = DAT_TYPE_KB;
pData[1] = ctrl_key;
memcpy(pData + 2, keycode, 6);
int fifo_use = (usb_ff_wptr - usb_ff_rptr) & (USB_FIFO_NUM*2-1);
if (fifo_use > USB_FIFO_NUM) {
usb_ff_rptr++;
//fifo overflow, overlap older data
}
return 0;
}
reg_usb_ep_ptr(USB_EDP_KEYBOARD_IN) = 0;
#if USB_SOFTWARE_CRC_CHECK
unsigned char crc_in[KEYBOARD_REPORT_KEY_MAX+2];
unsigned short crc;
unsigned int crch;
crc_in[0] = ctrl_key;
crc_in[1] = 0;
foreach(i, KEYBOARD_REPORT_KEY_MAX){
crc_in[i+2] = keycode[i];
}
crc = USB_CRC16 (crc_in, KEYBOARD_REPORT_KEY_MAX+2);
crch = crc >> 8;
if ((crch==0x06) || (crch==0x04) || (crch == 0x00))
{
unsigned int tmp = crc_in[2];
crc_in[2] = crc_in[3];
crc_in[3] = tmp;
}
// please refer to keyboard_report_desc
foreach(i, (KEYBOARD_REPORT_KEY_MAX+2)){
reg_usb_ep_dat(USB_EDP_KEYBOARD_IN) = crc_in[i];
}
#else
// please refer to keyboard_report_desc
reg_usb_ep_dat(USB_EDP_KEYBOARD_IN) = ctrl_key;
reg_usb_ep_dat(USB_EDP_KEYBOARD_IN) = 0;//resv
foreach(i, KEYBOARD_REPORT_KEY_MAX){
reg_usb_ep_dat(USB_EDP_KEYBOARD_IN) = keycode[i];
}
#endif
// reg_usb_ep_ctrl(USB_EDP_KEYBOARD_IN) = FLD_EP_DAT_ACK; // ACK
reg_usb_ep_ctrl(USB_EDP_KEYBOARD_IN) = FLD_EP_DAT_ACK | (edp_toggle[USB_EDP_KEYBOARD_IN] ? FLD_USB_EP_DAT1 : FLD_USB_EP_DAT0); // ACK
edp_toggle[USB_EDP_KEYBOARD_IN] ^= 1;
return 1;
}
static inline void usbkb_report_normal_key(int ctrl_key, u8 *keycode, int cnt){
if(cnt > 0 || ctrl_key){
if(usbkb_hid_report_normal(ctrl_key, keycode)){
BM_SET(usbkb_not_released, KB_NORMAL_RELEASE_MASK);
}
}else{
usbkb_release_normal_key();
}
}
static inline void usbkb_report_sys_key(u8 ext_key){
if(ext_key >= VK_SYS_START && ext_key < VK_SYS_END){
int idx = ext_key - VK_SYS_START;
if(usbmouse_hid_report(USB_HID_KB_SYS, (u8*)(&vk_sys_map[idx]), 1)){ // assert sys key len == 1, check descriptor
BM_SET(usbkb_not_released, KB_SYS_RELEASE_MASK);
}
}else{
usbkb_release_sys_key();
}
}
static inline void usbkb_report_media_key(u8 ext_key){
if(ext_key >= VK_MEDIA_START && ext_key < VK_MEDIA_END){
u8 ext_keycode[MOUSE_REPORT_DATA_LEN] = {0};
int idx = ext_key - VK_MEDIA_START;
foreach(i, VK_EXT_LEN){
ext_keycode[i] = vk_media_map[idx].val[i];
}
if(usbmouse_hid_report(USB_HID_KB_MEDIA, ext_keycode, MEDIA_REPORT_DATA_LEN)){
BM_SET(usbkb_not_released, KB_MEDIA_RELEASE_MASK);
}
}else{
usbkb_release_media_key();
}
}
void usbkb_report_consumer_key(u16 consumer_key)
{
if(consumer_key){
u8 ext_keycode[MOUSE_REPORT_DATA_LEN] = {0};
foreach(i, VK_EXT_LEN){
ext_keycode[i] = consumer_key;
consumer_key >>=8;
}
if(usbmouse_hid_report(USB_HID_KB_MEDIA, ext_keycode, MEDIA_REPORT_DATA_LEN)){
BM_SET(usbkb_not_released, KB_MEDIA_RELEASE_MASK);
}
}else{
usbkb_release_media_key();
}
usbkb_data_report_time = clock_time();
}
int kb_is_data_same(kb_data_t *a, kb_data_t *b){
if(!a || !b){
return 0;
}
if((a->cnt != b->cnt) || (a->ctrl_key != b->ctrl_key))
return 0;
foreach(i, a->cnt){
if(a->keycode[i] != b->keycode[i]){
return 0;
}
}
return 1;
}
static inline int usbkb_check_repeat_and_save(kb_data_t *data){
static kb_data_t last_data;
int same = kb_is_data_same(&last_data, data);
if(!same){
((u32*) (&last_data))[0] = ((u32*) (data))[0];
((u32*) (&last_data))[1] = ((u32*) (data))[1];
}
return same;
}
void usbkb_hid_report(kb_data_t *data){
u8 ext_key = VK_EXT_END, normal_key_cnt = 0;
u8 normal_keycode[KEYBOARD_REPORT_KEY_MAX] = {0};
if(data->cnt > KB_RETURN_KEY_MAX){ // must, in case bad packets
return;
}
/* http://msdn.microsoft.com/en-us/windows/hardware/gg462991.aspx
It is also important to notice that any re-triggering of events should be done by software timers in the host system and not by hardware timers in the device itself.
For example, if the user keeps pressing the Volume Increment button, the device should only generate one input report with this state information
*/
if((data->cnt > 0 || data->ctrl_key) && usbkb_check_repeat_and_save(data)){
if(usbkb_not_released){
usbkb_data_report_time = clock_time();
return;
}
}
if(data->cnt > 0){
normal_key_cnt = usbkb_separate_key_types(data->keycode, data->cnt, normal_keycode, &ext_key);
}
usbkb_report_normal_key(data->ctrl_key, normal_keycode, normal_key_cnt);
usbkb_report_sys_key(ext_key);
usbkb_report_media_key(ext_key);
usbkb_data_report_time = clock_time();
}
int usb_hid_report_fifo_proc(void)
{
if(usb_ff_rptr == usb_ff_wptr){
return 0;
}
u8 *pData = (u8 *)&usb_fifo[usb_ff_rptr & (USB_FIFO_NUM - 1)];
if(pData[0] == DAT_TYPE_KB){
if(usbhw_is_ep_busy(USB_EDP_KEYBOARD_IN)){
return 0;
}
else{
usbkb_hid_report_normal(pData[1], pData + 2);
usb_ff_rptr ++;
return 1;
}
}
else if(pData[0] == DAT_TYPE_MOUSE){
if(usbhw_is_ep_busy(USB_EDP_MOUSE)){
return 0;
}
else{
usbmouse_hid_report(pData[1], pData + 4, pData[2]);
usb_ff_rptr ++;
return 1;
}
}
return 0;
}
+70
View File
@@ -0,0 +1,70 @@
/********************************************************************************************************
* @file usbkb.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include <application/usbstd/HIDClassCommon.h>
#include <application/usbstd/HIDReportData.h>
#include "tl_common.h"
#include "drivers.h"
#include "application/keyboard/keyboard.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
#define DAT_TYPE_KB 1
#define DAT_TYPE_MOUSE 2
#define USB_FIFO_NUM 4
#define USB_FIFO_SIZE 8
extern u8 usb_fifo[USB_FIFO_NUM][USB_FIFO_SIZE];
extern u8 usb_ff_rptr;
extern u8 usb_ff_wptr;
#define KEYBOARD_REPORT_KEY_MAX 6
typedef struct {
u8 Modifier; /**< Keyboard modifier byte, indicating pressed modifier keys (a combination of
* \c HID_KEYBOARD_MODIFER_* masks).
*/
u8 Reserved; /**< Reserved for OEM use, always set to 0. */
u8 KeyCode[KEYBOARD_REPORT_KEY_MAX]; /**< Key codes of the currently pressed keys. */
} usbkb_hid_report_t;
void usbkb_report_consumer_key(u16 consumer_key);
void usbkb_hid_report(kb_data_t *data);
int usb_hid_report_fifo_proc(void);
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+130
View File
@@ -0,0 +1,130 @@
/********************************************************************************************************
* @file usbkb_i.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include "usbkb.h"
#include "application/usbstd/usb.h"
/** HID class report descriptor. This is a special descriptor constructed with values from the
* USBIF HID class specification to describe the reports and capabilities of the HID device. This
* descriptor is parsed by the host and its contents used to determine what data (and in what encoding)
* the device will send, and what it may be sent back from the host. Refer to the HID specification for
* more details on HID report descriptors.
*/
static const USB_Descriptor_HIDReport_Datatype_t keyboard_report_desc[] = {
HID_DESCRIPTOR_KEYBOARD(KEYBOARD_REPORT_KEY_MAX),
};
static inline u8* usbkb_get_report_desc(void) {
return (u8*) (keyboard_report_desc);
}
static inline u16 usbkb_get_report_desc_size(void) {
return sizeof(keyboard_report_desc);
}
#if (AUDIO_HOGP)
static const USB_Descriptor_HIDReport_Datatype_t audio_hogp_report_desc[] = {
0x06, 0x01, 0xFF, // Usage Page (Vendor Defined 0xFF01)
0x09, 0x02, // Usage (tmp usage)
0xA1, 0x02, // Collection (Logical)
0x85, 0x02, // Report ID (2)
0x09, 0x14, // Usage (tmp usage)
0x75, 0x08, // Report Size (8)
0x95, 0x14, // Report Count (20)
0x15, 0x80, // Logical Minimum (128)
0x25, 0x7F, // Logical Maximum (127)
0x81, 0x22, // Input (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position)
0x85, 0x0a, // Report ID (10)
0x09, 0x14, // Usage (tmp usage)
0x75, 0x08, // Report Size (8)
0x95, 0x14, // Report Count (20)
0x15, 0x80, // Logical Minimum (128)
0x25, 0x7F, // Logical Maximum (127)
0x81, 0x22, // Input (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position)
0x85, 0x0b, // Report ID (11)
0x09, 0x14, // Usage (tmp usage)
0x75, 0x08, // Report Size (8)
0x95, 0x14, // Report Count (20)
0x15, 0x80, // Logical Minimum (128)
0x25, 0x7F, // Logical Maximum (127)
0x81, 0x22, // Input (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position)
0x85, 0x0c, // Report ID (12)
0x09, 0x14, // Usage (tmp usage)
0x75, 0x08, // Report Size (8)
0x95, 0x14, // Report Count (20)
0x15, 0x80, // Logical Minimum (128)
0x25, 0x7F, // Logical Maximum (127)
0x81, 0x22, // Input (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position)
0x85, 0x04, // Report ID (4)
0x09, 0x04, // Usage (tmp usage)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output
0xC0, // End Collection
};
static const USB_Descriptor_HIDReport_Datatype_t vendor_report_desc[] = {
0x06, 0x01, 0xFF, // Usage Page (Vendor Defined 0xFF01)
0x09, 0x02, // Usage (tmp usage)
0xA1, 0x02, // Collection (Logical)
0x85, 0x03, // Report ID (3)
0x09, 0x14, // Usage (tmp usage)
0x75, 0x08, // Report Size (8)
0x95, 0x20, // Report Count (20)
0x15, 0x80, // Logical Minimum (128)
0x25, 0x7F, // Logical Maximum (127)
0x81, 0x22, // Input (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position)
0x85, 0x04, // Report ID (4)
0x09, 0x04, // Usage (tmp usage)
0x75, 0x08, // Report Size (8)
0x95, 0x20, // Report Count (1)
0x91, 0x02, // Output
0xC0, // End Collection
};
static inline u8* usbaudio_hogp_get_report_desc(void) {
return (u8*) (audio_hogp_report_desc);
}
static inline u16 usbaudio_hogp_get_report_desc_size(void) {
return sizeof(audio_hogp_report_desc);
}
static inline u8* usb_vendor_get_report_desc(void) {
return (u8*) (vendor_report_desc);
}
static inline u16 usb_vendor_get_report_desc_size(void) {
return sizeof(vendor_report_desc);
}
#endif
+152
View File
@@ -0,0 +1,152 @@
/********************************************************************************************************
* @file usbmouse.c
*
* @brief This is the source file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#include "tl_common.h"
#if(USB_MOUSE_ENABLE)
#include "usbmouse.h"
#include "usbkb.h"
#include "application/usbstd/usb.h"
#include "application/rf_frame.h"
#ifndef USB_MOUSE_REPORT_SMOOTH
#define USB_MOUSE_REPORT_SMOOTH 0
#endif
#define USBMOUSE_BUFF_DATA_NUM 8
static mouse_data_t mouse_dat_buff[USBMOUSE_BUFF_DATA_NUM];
static u8 usbmouse_wptr, usbmouse_rptr;
static u32 usbmouse_not_released;
static u32 usbmouse_data_report_time;
void usbmouse_add_frame (rf_packet_mouse_t *packet_mouse){
u8 new_data_num = packet_mouse->pno;
for(u8 i=0;i<new_data_num;i++)
{
// tmemcpy4((int*)(&mouse_dat_buff[usbmouse_wptr]), (int*)(&packet_mouse->data[i*sizeof(mouse_data_t)]), sizeof(mouse_data_t));
memcpy((s8*)(&mouse_dat_buff[usbmouse_wptr]), (s8*)(&packet_mouse->data[i*sizeof(mouse_data_t)]), sizeof(mouse_data_t));
BOUND_INC_POW2(usbmouse_wptr,USBMOUSE_BUFF_DATA_NUM);
if(usbmouse_wptr == usbmouse_rptr)
{
//BOUND_INC_POW2(usbmouse_rptr,USBMOUSE_BUFF_DATA_NUM);
break;
}
}
}
void usbmouse_release_check(){
if(usbmouse_not_released && clock_time_exceed(usbmouse_data_report_time, USB_MOUSE_RELEASE_TIMEOUT)){
u32 release_data = 0;
if(usbmouse_hid_report(USB_HID_MOUSE, (u8*)(&release_data), MOUSE_REPORT_DATA_LEN)){
usbmouse_not_released = 0;
}
}
}
void usbmouse_report_frame(){
#if USB_MOUSE_REPORT_SMOOTH
static u32 tick = 0;
if(usbhw_is_ep_busy(USB_EDP_MOUSE)) {
tick = clock_time ();
}
u8 diff = (usbmouse_wptr - usbmouse_rptr) & (USBMOUSE_BUFF_DATA_NUM - 1);
if (diff < 3 && !clock_time_exceed (tick, 5000)) {
return;
}
#endif
if(usbmouse_wptr != usbmouse_rptr){
u32 data = *(u32*)(&mouse_dat_buff[usbmouse_rptr]); // that is > 0
int ret = usbmouse_hid_report(USB_HID_MOUSE,(u8*)(&data), MOUSE_REPORT_DATA_LEN);
if(ret){
BOUND_INC_POW2(usbmouse_rptr,USBMOUSE_BUFF_DATA_NUM);
}
if(0 == data && ret){ // successfully release the key
usbmouse_not_released = 0;
}else{
usbmouse_not_released = 1;
usbmouse_data_report_time = clock_time();
}
}
return;
}
int usbmouse_hid_report(u8 report_id, u8 *data, int cnt){
//unsigned char crc_in[8];
//unsigned short crc;
//unsigned int crch;
if(usbhw_is_ep_busy(USB_EDP_MOUSE)){
u8 *pData = (u8 *)&usb_fifo[usb_ff_wptr++ & (USB_FIFO_NUM - 1)];
pData[0] = DAT_TYPE_MOUSE;
pData[1] = report_id;
pData[2] = cnt;
memcpy(pData + 4, data, cnt);
int fifo_use = (usb_ff_wptr - usb_ff_rptr) & (USB_FIFO_NUM*2-1);
if (fifo_use > USB_FIFO_NUM) {
usb_ff_rptr++;
//fifo overflow, overlap older data
}
return 0;
}
reg_usb_ep_ptr(USB_EDP_MOUSE) = 0;
// please refer to usbmouse_i.h mouse_report_desc
extern u8 usb_mouse_report_proto;
if (!usb_mouse_report_proto) {
reg_usb_ep_dat(USB_EDP_MOUSE) = data[0];
reg_usb_ep_dat(USB_EDP_MOUSE) = data[1];
reg_usb_ep_dat(USB_EDP_MOUSE) = data[2];
}
else {
reg_usb_ep_dat(USB_EDP_MOUSE) = report_id;
foreach(i, cnt){
reg_usb_ep_dat(USB_EDP_MOUSE) = data[i];
}
}
// reg_usb_ep_ctrl(USB_EDP_MOUSE) = FLD_EP_DAT_ACK; // ACK
reg_usb_ep_ctrl(USB_EDP_MOUSE) = FLD_EP_DAT_ACK | (edp_toggle[USB_EDP_MOUSE] ? FLD_USB_EP_DAT1 : FLD_USB_EP_DAT0); // ACK
edp_toggle[USB_EDP_MOUSE] ^= 1;
return 1;
}
#endif
+45
View File
@@ -0,0 +1,45 @@
/********************************************************************************************************
* @file usbmouse.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include <application/usbstd/HIDClassCommon.h>
#include <application/usbstd/HIDReportData.h>
#include "tl_common.h"
#include "drivers.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
#define MOUSE_REPORT_DATA_LEN (sizeof(mouse_data_t))
#define MEDIA_REPORT_DATA_LEN 4
int usbmouse_hid_report(u8 report_id, u8 *data, int cnt);
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+255
View File
@@ -0,0 +1,255 @@
/********************************************************************************************************
* @file usbmouse_i.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include "usbmouse.h"
#include "application/usbstd/usb.h"
#include "vendor/common/default_config.h"
/** HID class report descriptor. This is a special descriptor constructed with values from the
* USBIF HID class specification to describe the reports and capabilities of the HID device. This
* descriptor is parsed by the host and its contents used to determine what data (and in what encoding)
* the device will send, and what it may be sent back from the host. Refer to the HID specification for
* more details on HID report descriptors.
*/
/* debug note: */
/*
0x85, 0x01, //Report ID (1) keyboard
0x85, 0x02, //report ID 02 mouse
*/
static const USB_Descriptor_HIDReport_Datatype_t mouse_report_desc[] = {
#if 0
HID_RPT_USAGE_PAGE(8, 0x01), /* Generic Desktop */
HID_RPT_USAGE(8, 0x02) , /* Mouse */
HID_RPT_COLLECTION(8, 0x01) , /* Application */
HID_RPT_REPORT_ID(8, USB_HID_MOUSE) , /*Report ID*/
HID_RPT_USAGE_PAGE(8, 0x09) , /* Button */
// 1 is mouse left button,2 is mouse right button,3 is central buuton
HID_RPT_USAGE_MINIMUM(8, 0x01) ,
HID_RPT_USAGE_MAXIMUM(8, 0x05),
HID_RPT_LOGICAL_MINIMUM(8, 0x00) ,
HID_RPT_LOGICAL_MAXIMUM(8, 0x01),
HID_RPT_REPORT_SIZE(8, 0x01),
HID_RPT_REPORT_COUNT(8, 0x05), /* debug note: 3->5*/
HID_RPT_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
HID_RPT_REPORT_SIZE(8, 0x03), /* debug note: 5->3*/
HID_RPT_REPORT_COUNT(8, 0x01),
HID_RPT_INPUT(8, HID_IOF_CONSTANT),
HID_RPT_USAGE(8, 0x01), /* Pointer */
HID_RPT_COLLECTION(8, 0x00), /* Physical */
HID_RPT_USAGE_PAGE(8, 0x01), /* Generic Desktop */
HID_RPT_USAGE(8, 0x30), /* Usage X */
HID_RPT_USAGE(8, 0x31), /* Usage Y */
HID_RPT_LOGICAL_MINIMUM(8, 0x81), // LOGICAL_MINIMUM (-127)
HID_RPT_LOGICAL_MAXIMUM(8, 0x7f), // LOGICAL_MAXIMUM (127)
HID_RPT_REPORT_SIZE(8, 0x08),
HID_RPT_REPORT_COUNT(8, 0x02),
HID_RPT_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
HID_RPT_USAGE(8, 0x38), /* Usage Wheel */
HID_RPT_LOGICAL_MINIMUM(8, 0x81), //LOGICAL_MINIMUM (-127)
HID_RPT_LOGICAL_MAXIMUM(8, 0x7f), //LOGICAL_MAXIMUM (127)
HID_RPT_REPORT_SIZE(8, 0x08), //REPORT_SIZE (8)
HID_RPT_REPORT_COUNT(8, 0x01), //REPORT_COUNT (1)
HID_RPT_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
HID_RPT_END_COLLECTION(0),
HID_RPT_END_COLLECTION(0),
HID_RPT_USAGE_PAGE(8, 0x0c), //global, usage page (follow 1 bytes) consumer page
HID_RPT_USAGE(8, 0x01), //local, usage ID 01 Consumer Control
HID_RPT_COLLECTION(8, 0x01), //main, collection
HID_RPT_REPORT_ID(8, USB_HID_KB_MEDIA), //Report ID
HID_RPT_REPORT_SIZE(8, 0x10), //global, report size 16 bits
HID_RPT_REPORT_COUNT(8, 0x02), //global, report count 2
HID_RPT_LOGICAL_MINIMUM(8, 0x01), //global, min 0x01
HID_RPT_LOGICAL_MAXIMUM(16, 0x02ff), //global, max 0x028c
HID_RPT_USAGE_MINIMUM(8, 0x01), //local, min 0x01
HID_RPT_USAGE_MAXIMUM(16, 0x02ff), //local, max 0x28c
HID_RPT_INPUT(8, HID_IOF_ABSOLUTE), //main, input data varible, absolute
HID_RPT_END_COLLECTION(0), //main, end collection
HID_RPT_USAGE_PAGE(8, 0x01), //gobal, USAGE_PAGE 1 (Generic Desktop)
HID_RPT_USAGE(8, 0x80), //local, usage ID 0x80 system control
HID_RPT_COLLECTION(8, 0x01), //main conllection
HID_RPT_REPORT_ID(8, USB_HID_KB_SYS), //Report ID
HID_RPT_REPORT_SIZE(8, 0x01), //global, report size 2
HID_RPT_REPORT_COUNT(8, 0x03), //report count 1
HID_RPT_LOGICAL_MINIMUM(8, 0x00), //global min 01
HID_RPT_LOGICAL_MAXIMUM(8, 0x01), //gobal, max 3
HID_RPT_USAGE(8, 0x81), //local usage ID 0x81 system power down
HID_RPT_USAGE(8, 0x82), //local usage ID 0x82 system sleep
HID_RPT_USAGE(8, 0x83), //local usage ID 0x83 system wakeup
HID_RPT_INPUT(8, HID_IOF_ABSOLUTE|HID_IOF_NO_PREFERRED_STATE|HID_IOF_NULLSTATE),
HID_RPT_REPORT_SIZE(8, 0x05), //global report size 6
HID_RPT_REPORT_COUNT(8, 0x01), //report count 1
HID_RPT_INPUT(8, HID_IOF_CONSTANT|HID_IOF_VARIABLE),
HID_RPT_END_COLLECTION(0), //end of collection
#else
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x85, USB_HID_MOUSE, //report ID 01
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
// 1 is mouse left button,2 is mouse right button,3 is central buuton
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x05, // USAGE_MAXIMUM (Button 5)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x05, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x81, 0x01, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (16)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x06, // INPUT (Data,Var,Rel)
0x09, 0x38, // USAGE (Wheel)
0x15, 0x81, //LOGICAL_MINIMUM (-127)
0x25, 0x7f, //LOGICAL_MAXIMUM (127)
0x75, 0x08, //REPORT_SIZE (16)
0x95, 0x01, //REPORT_COUNT (1)
0x81, 0x06, //INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
#if (ONEKEY_WEB==0)
// begin of media key
0x05,0x0c, //global, usage page (follow 1 bytes) consumer page
0x09,0x01, //local, usage ID 01 Consumer Control
0xA1,0x01, //main, collection
0x85,USB_HID_KB_MEDIA, //global, report ID 0x03
0x75,0x10, //global, report size 16 bits
0x95,0x02, //global, report count 2
0x15,0x01, //global, min 0x01
0x26,0x9c,0x02, //global, max 0x29c
#if CHIP_EOP_ERROR
0x19,0x01, //local, min 0x01
0x2a,0xff,0x02, //local, max 0x2ff
#else
0x19,0x01, //local, min 0x01
0x2a,0x8c,0x02, //local, max 0x28c
#endif
0x81,0x00, //main, input data varible, absolute
0xc0, //main, end collection
0x05,0x01, //gobal, USAGE_PAGE 1 (Generic Desktop)
0x09,0x80, //local, usage ID 0x80 system control
0xa1,0x01, //main conllection
0x85,USB_HID_KB_SYS, //global report ID 0x4
0x75,0x02, //global, report size 2
0x95,0x01, //report count 1
0x15,0x01, //global min 01
0x25,0x03, //gobal, max 3
0x09,0x82, //local usage ID 0x82 system sleep
0x09,0x81, //local usage ID 0x81 system power down
0x09,0x83, //local usage ID 0x83 system wakeup
0x81,0x60, //main, input data, var, abs, No Prefer, NULL state
0x75,0x06, //global report size 6
0x81,0x03, //main input, constant, array
0xc0, //end of collection
// end of media key
#endif
#endif
//need Jensen's help: report ID 5
HID_RPT_USAGE_PAGE(8, 0x01), //global, USAGE_PAGE 1 (Generic Desktop)
0x09,0x00, //usage undefined
0xa1,0x01, //main collection
0x85,0x05, //global report ID 0x5
0x06,0x00,0xff, //global usage page
0x09,0x01, //local, usage ID 01 Consumer Control
0x15,0x81, //global min 81
0x25,0x7f, //global, max 7f
0x75,0x08, //global, report size 8
0x95,0x07, //report count 7
0xb1,0x02, //feature (data, var, abs)
HID_RPT_END_COLLECTION(0), //main, end collection
};
static inline u8* usbmouse_get_report_desc(void) {
return (u8*) (mouse_report_desc);
}
static inline u16 usbmouse_get_report_desc_size(void) {
return sizeof(mouse_report_desc);
}
+506
View File
@@ -0,0 +1,506 @@
/********************************************************************************************************
* @file adpcm.c
*
* @brief This is the source file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#include "tl_common.h"
#include "drivers.h"
#include "audio_config.h"
#include "adpcm.h"
#if (TL_AUDIO_MODE & TL_AUDIO_MASK_ADPCM_MODE) //Adpcm mode
static const signed char idxtbl[] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8};
static const unsigned short steptbl[] = {
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 };
#define NUM_OF_ORIG_SAMPLE 2
#if (TL_AUDIO_MODE & RCU_PROJECT) //RCU
#if (TL_AUDIO_MODE == TL_AUDIO_RCU_ADPCM_GATT_TLEINK) //RCU,GATT TELINK
/////////////////////////////////////////////////////////////////////////////////
// 256-samples split into 2
/////////////////////////////////////////////////////////////////////////////////
void mic_to_adpcm_split (signed short *ps, int len, signed short *pds, int start)
{
int i, j;
unsigned short code=0;
unsigned short code16=0;
static int predict_idx = 0;
code = 0;
static signed short *pd;
static int predict;
//byte2,byte1: predict; byte3: predict_idx; byte4:adpcm data len
if (start)
{
pd = pds;
*pd++ = predict;
* (((signed char *)pds) + 2)= predict_idx;
* (((unsigned char *)pds) + 3)= (ADPCM_PACKET_LEN - 4);
pd++;
}
//byte5- byte128: 124 byte(62 sample) adpcm data
for (i=0; i<len; i++) {
s16 di = ps[i];
int step = steptbl[predict_idx];
int diff = di - predict;
if (diff >=0 ) {
code = 0;
}
else {
diff = -diff;
code = 8;
}
int diffq = step >> 3;
for (j=4; j>0; j=j>>1) {
if( diff >= step) {
diff = diff - step;
diffq = diffq + step;
code = code + j;
}
step = step >> 1;
}
code16 = (code16 >> 4) | (code << 12);
if ( (i&3) == 3) {
*pd++ = code16;
}
if(code >= 8) {
predict = predict - diffq;
}
else {
predict = predict + diffq;
}
if (predict > 32767) {
predict = 32767;
}
else if (predict < -32768) {
predict = -32768;
}
predict_idx = predict_idx + idxtbl[code];
if(predict_idx < 0) {
predict_idx = 0;
}
else if(predict_idx > 88) {
predict_idx = 88;
}
}
}
#elif (TL_AUDIO_MODE == TL_AUDIO_RCU_ADPCM_GATT_GOOGLE) //RCU,GATT GOOGLE
#define ADPCM_ANDROID_ID 0x00
static int serial_id = 0;
unsigned short adpcm_serial_num = 0;
_attribute_ram_code_ void mic_to_adpcm_split (signed short *ps, int len, signed short *pds, int start)
{
int i, j;
unsigned short code=0;
unsigned short code16=0;
static signed short *pd;
static int predict_idx = 1;
code = 0;
static int predict;
//Seq# 2bytes; Id: 1bytes; Prev.pred: 2bytes; index: 1bytes
if (start)
{
pd = pds;
*pd++ = ((adpcm_serial_num>>8)&0x00ff)|((adpcm_serial_num<<8)&0xff00);
*pd++ = (ADPCM_ANDROID_ID)|((predict&0xff00));
*pd++ = ((predict)&0x00ff)|((predict_idx<<8)&0xff00);
adpcm_serial_num ++;
}
for(i=0 ; i<len; i++){//unit sample
s16 di = ps[i];
int step = steptbl[predict_idx];
int diff = di - predict;
if(diff >= 0){
code = 0;
}else{
diff = -diff;
code = 8;
}
int diffq = step >> 3;
for(j=4; j>0; j=j>>1){
if(diff >= step){
diff = diff - step;
diffq = diffq + step;
code = code + j;
}
step = step >> 1;
}
code16 = (code16 >> 4) | (code << 12);
if((i&3) == 3){
code16 = ((code16&0x0f)<<4)|((code16&0xf0)>>4) | ((code16&0x0f00)<<4)|((code16&0xf000)>>4);
*pd++ = code16;
}
if(code >= 8) {
predict = predict - diffq;
}else {
predict = predict + diffq;
}
if(predict > 32767){
predict = 32767;
}else if (predict < -32768) {
predict = -32768;
}
predict_idx = predict_idx + idxtbl[code];
if(predict_idx < 0) {
predict_idx = 0;
}else if(predict_idx > 88){
predict_idx = 88;
}
}
}
#elif (TL_AUDIO_MODE & TL_AUDIO_MASK_HID_SERVICE_CHANNEL) //RCU,HID SERVICE
int predict = 0;
int predict_idx = 0;
/////////////////////////////////////////////////////////////////////////////////
// 256-samples split into 2
/////////////////////////////////////////////////////////////////////////////////
_attribute_ram_code_ void mic_to_adpcm_split (signed short *ps, int len, signed short *pds, int start)
{
int i, j;
unsigned short code=0;
unsigned short code16=0;
static signed short *pd;
pd = pds;
code = 0;
for (i=0; i<len; i++) {
s16 di = ps[i];
int step = steptbl[predict_idx];
int diff = di - predict;
if (diff >=0 ) {
code = 0;
}
else {
diff = -diff;
code = 8;
}
int diffq = step >> 3;
for (j=4; j>0; j=j>>1) {
if( diff >= step) {
diff = diff - step;
diffq = diffq + step;
code = code + j;
}
step = step >> 1;
}
code16 = (code16 >> 4) | (code << 12);
if ( (i&3) == 3) {
code16 = ((code16&0x0f)<<4)|((code16&0xf0)>>4) | ((code16&0x0f00)<<4)|((code16&0xf000)>>4);
*pd++ = code16;
}
if(code >= 8) {
predict = predict - diffq;
}
else {
predict = predict + diffq;
}
if (predict > 32767) {
predict = 32767;
}
else if (predict < -32768) {
predict = -32768;
}
predict_idx = predict_idx + idxtbl[code & 15];
if(predict_idx < 0) {
predict_idx = 0;
}
else if(predict_idx > 88) {
predict_idx = 88;
}
}
}
#else
#endif//end RCU_PROJECT pcm to adpcm
#elif (TL_AUDIO_MODE & DONGLE_PROJECT) //Dongle
#if (TL_AUDIO_MODE == TL_AUDIO_DONGLE_ADPCM_GATT_TELINK) //Dongle,GATT TELINK
void adpcm_to_pcm (signed short *ps, signed short *pd, int len)
{
int i;
//byte2,byte1: predict; byte3: predict_idx; byte4:adpcm data len
int predict = ps[0];
int predict_idx = ps[1] & 0xff;
// int adpcm_len = (ps[1]>>8) & 0xff;
unsigned char *pcode = (unsigned char *) (ps + NUM_OF_ORIG_SAMPLE);
unsigned char code;
code = *pcode ++;
//byte5- byte128: 124 byte(62 sample) adpcm data
for (i=0; i<len; i++) {
if (1) {
int step = steptbl[predict_idx];
int diffq = step >> 3;
if (code & 4) {
diffq = diffq + step;
}
step = step >> 1;
if (code & 2) {
diffq = diffq + step;
}
step = step >> 1;
if (code & 1) {
diffq = diffq + step;
}
if (code & 8) {
predict = predict - diffq;
}
else {
predict = predict + diffq;
}
if (predict > 32767) {
predict = 32767;
}
else if (predict < -32768) {
predict = -32768;
}
predict_idx = predict_idx + idxtbl[code & 15];
if(predict_idx < 0) {
predict_idx = 0;
}
else if(predict_idx > 88) {
predict_idx = 88;
}
if (i&1) {
code = *pcode ++;
}
else {
code = code >> 4;
}
}
if (0 && i < NUM_OF_ORIG_SAMPLE) {
*pd++ = ps[i];
}
else {
*pd++ = predict;
}
}
}
#elif (TL_AUDIO_MODE == TL_AUDIO_DONGLE_ADPCM_GATT_GOOGLE) //Dongle,GATT GOOGLE
#define ADPCM_ANDROID_ID 0x00
_attribute_ram_code_ void adpcm_to_pcm (signed short *ps, signed short *pd, int len)
{
int i;
int predict = (s16)((ps[1]&0xff00) | (ps[2]&0x00ff));
int predict_idx = (s8)((ps[2]&0xff00)>>8);
unsigned char *pcode = (unsigned char *) (ps + 3);
unsigned char code;
code = *pcode ++;
code = ((code>>4)&0x0f)|((code<<4)&0xf0);
//google: byte7-byte134: 128 byte(62 sample) adpcm data
//t4h: byte5-byte100: 96 byte(48 sample) adpcm data
for(i=0; i<len; i++){
int step = steptbl[predict_idx];
int diffq = step >> 3;
if(code & 4){
diffq = diffq + step;
}
step = step >> 1;
if(code & 2){
diffq = diffq + step;
}
step = step >> 1;
if(code & 1){
diffq = diffq + step;
}
if(code & 8){
predict = predict - diffq;
}else{
predict = predict + diffq;
}
if(predict > 32767){
predict = 32767;
}else if(predict < -32768){
predict = -32768;
}
predict_idx = predict_idx + idxtbl[code & 15];
if(predict_idx < 0){
predict_idx = 0;
}else if(predict_idx > 88){
predict_idx = 88;
}
if(i&1){
code = *pcode ++;
code = ((code>>4)&0x0f)|((code<<4)&0xf0); //add by qiuwei for android 8
}else{
code = code >> 4;
}
if (0 && i < NUM_OF_ORIG_SAMPLE) {
*pd++ = ps[i];
}
else {
*pd++ = predict;
}
}
}
#elif (TL_AUDIO_MODE & TL_AUDIO_MASK_HID_SERVICE_CHANNEL) //Dongle,HID SERVICE
int predict = 0;
int predict_idx = 0;
void adpcm_to_pcm (signed short *ps, signed short *pd, int len)
{
int i;
unsigned char *pcode = (unsigned char *) ps;
unsigned char code;
code = *pcode ++;
code = ((code>>4)&0x0f)|((code<<4) &0xf0);
for (i=0; i<len; i++) {
if (1) {
int step = steptbl[predict_idx];
int diffq = step >> 3;
if (code & 4) {
diffq = diffq + step;
}
step = step >> 1;
if (code & 2) {
diffq = diffq + step;
}
step = step >> 1;
if (code & 1) {
diffq = diffq + step;
}
if (code & 8) {
predict = predict - diffq;
}
else {
predict = predict + diffq;
}
if (predict > 32767) {
predict = 32767;
}
else if (predict < -32768) {
predict = -32768;
}
predict_idx = predict_idx + idxtbl[code & 15];
if(predict_idx < 0) {
predict_idx = 0;
}
else if(predict_idx > 88) {
predict_idx = 88;
}
if (i&1) {
code = *pcode ++;
code = ((code>>4)&0x0f)|((code<<4) &0xf0);
}
else {
code = code >> 4;
}
}
if (0 && i < NUM_OF_ORIG_SAMPLE) {
*pd++ = ps[i];
}
else {
*pd++ = predict;
}
}
}
#else
#endif//end DONGLE_PROJECT adpcm to pcm
#endif//end RCU_PROJECT OR DONGLE_PROJECT
#endif
+29
View File
@@ -0,0 +1,29 @@
/********************************************************************************************************
* @file adpcm.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#ifndef ADPCM_H_
#define ADPCM_H_
void mic_to_adpcm_split (signed short *ps, int len, signed short *pds, int start);
void adpcm_to_pcm (signed short *ps, signed short *pd, int len);
#endif /* ADPCM_H_ */
+84
View File
@@ -0,0 +1,84 @@
/********************************************************************************************************
* @file audio_common.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#ifndef AUDIO_COMMON_H_
#define AUDIO_COMMON_H_
#define TL_AUDIO_MASK_SBC_MODE (0x00000001)
#define TL_AUDIO_MASK_MSBC_MODE (0x00000002)
#define TL_AUDIO_MASK_ADPCM_MODE (0x00000004)
#define TL_AUDIO_MASK_OPUS_MODE (0x00000008)
#define TL_AUDIO_MASK_HID_SERVICE_CHANNEL (0x00000100)
#define TL_AUDIO_MASK_GATT_SERVICE_TELINK_CHANNEL (0x00000200)
#define TL_AUDIO_MASK_GATT_SERVICE_GOOGLE_CHANNEL (0x00000400)
#define TL_AUDIO_MASK_GATT_SERVICE_AMAZON_CHANNEL (0x00000800)
#define TL_AUDIO_MASK_DONGLE_TO_STB (0x00010000)
#define RCU_PROJECT (0x01000000)
#define DONGLE_PROJECT (0x02000000)
#define AUDIO_DISABLE 0
//RCU Audio Mode
#define TL_AUDIO_RCU_ADPCM_GATT_TLEINK (RCU_PROJECT | TL_AUDIO_MASK_ADPCM_MODE | TL_AUDIO_MASK_GATT_SERVICE_TELINK_CHANNEL)
#define TL_AUDIO_RCU_ADPCM_GATT_GOOGLE (RCU_PROJECT | TL_AUDIO_MASK_ADPCM_MODE | TL_AUDIO_MASK_GATT_SERVICE_GOOGLE_CHANNEL)
#define TL_AUDIO_RCU_ADPCM_HID (RCU_PROJECT | TL_AUDIO_MASK_ADPCM_MODE | TL_AUDIO_MASK_HID_SERVICE_CHANNEL)
#define TL_AUDIO_RCU_SBC_HID (RCU_PROJECT | TL_AUDIO_MASK_SBC_MODE | TL_AUDIO_MASK_HID_SERVICE_CHANNEL)
#define TL_AUDIO_RCU_ADPCM_HID_DONGLE_TO_STB (RCU_PROJECT | TL_AUDIO_MASK_ADPCM_MODE | TL_AUDIO_MASK_HID_SERVICE_CHANNEL | TL_AUDIO_MASK_DONGLE_TO_STB)
#define TL_AUDIO_RCU_SBC_HID_DONGLE_TO_STB (RCU_PROJECT | TL_AUDIO_MASK_SBC_MODE | TL_AUDIO_MASK_HID_SERVICE_CHANNEL | TL_AUDIO_MASK_DONGLE_TO_STB)
#define TL_AUDIO_RCU_MSBC_HID (RCU_PROJECT | TL_AUDIO_MASK_MSBC_MODE | TL_AUDIO_MASK_HID_SERVICE_CHANNEL)
#define TL_AUDIO_RCU_OPUS_GATT_AMAZON (RCU_PROJECT | TL_AUDIO_MASK_OPUS_MODE | TL_AUDIO_MASK_GATT_SERVICE_AMAZON_CHANNEL)
//Dongle Audio Mode
#define TL_AUDIO_DONGLE_ADPCM_GATT_TELINK (DONGLE_PROJECT | TL_AUDIO_MASK_ADPCM_MODE | TL_AUDIO_MASK_GATT_SERVICE_TELINK_CHANNEL)
#define TL_AUDIO_DONGLE_ADPCM_GATT_GOOGLE (DONGLE_PROJECT | TL_AUDIO_MASK_ADPCM_MODE | TL_AUDIO_MASK_GATT_SERVICE_GOOGLE_CHANNEL)
#define TL_AUDIO_DONGLE_ADPCM_HID (DONGLE_PROJECT | TL_AUDIO_MASK_ADPCM_MODE | TL_AUDIO_MASK_HID_SERVICE_CHANNEL)
#define TL_AUDIO_DONGLE_SBC_HID (DONGLE_PROJECT | TL_AUDIO_MASK_SBC_MODE | TL_AUDIO_MASK_HID_SERVICE_CHANNEL)
#define TL_AUDIO_DONGLE_ADPCM_HID_DONGLE_TO_STB (DONGLE_PROJECT | TL_AUDIO_MASK_ADPCM_MODE | TL_AUDIO_MASK_HID_SERVICE_CHANNEL | TL_AUDIO_MASK_DONGLE_TO_STB)
#define TL_AUDIO_DONGLE_SBC_HID_DONGLE_TO_STB (DONGLE_PROJECT | TL_AUDIO_MASK_SBC_MODE | TL_AUDIO_MASK_HID_SERVICE_CHANNEL | TL_AUDIO_MASK_DONGLE_TO_STB)
#define TL_AUDIO_DONGLE_MSBC_HID (DONGLE_PROJECT | TL_AUDIO_MASK_MSBC_MODE | TL_AUDIO_MASK_HID_SERVICE_CHANNEL)
#define TL_AUDIO_DONGLE_OPUS_GATT_AMAZON (DONGLE_PROJECT | TL_AUDIO_MASK_OPUS_MODE | TL_AUDIO_MASK_GATT_SERVICE_AMAZON_CHANNEL)
#endif /* AUDIO_COMMON_H_ */
+47
View File
@@ -0,0 +1,47 @@
/********************************************************************************************************
* @file audio_config.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#include "application/audio/audio_common.h"
#include "tl_common.h"
#ifndef TL_AUDIO_MODE
#define TL_AUDIO_MODE AUDIO_DISABLE
#endif
#if (TL_AUDIO_MODE & RCU_PROJECT) //RCU
#if (TL_AUDIO_MODE == TL_AUDIO_RCU_ADPCM_GATT_TLEINK)
#define ADPCM_PACKET_LEN 128
#define TL_MIC_ADPCM_UNIT_SIZE 248
#define TL_MIC_BUFFER_SIZE 992
#endif
#elif (TL_AUDIO_MODE & DONGLE_PROJECT) //Dongle
#if (TL_AUDIO_MODE == TL_AUDIO_DONGLE_ADPCM_GATT_TELINK)
#define MIC_ADPCM_FRAME_SIZE 128
#define MIC_SHORT_DEC_SIZE 248
#endif
#else
#endif
+555
View File
@@ -0,0 +1,555 @@
/********************************************************************************************************
* @file tl_audio.c
*
* @brief This is the source file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#include "tl_common.h"
#include "drivers.h"
#include "tl_audio.h"
#include "audio_config.h"
#include "adpcm.h"
#if (TL_AUDIO_MODE & RCU_PROJECT) //RCU
#if (TL_AUDIO_MODE & (TL_AUDIO_MASK_SBC_MODE | TL_AUDIO_MASK_MSBC_MODE))
u8 buffer_mic_enc[(ADPCM_PACKET_LEN+3)*TL_MIC_PACKET_BUFFER_NUM];
#else
#define BUFFER_PACKET_SIZE ((ADPCM_PACKET_LEN >> 2) * TL_MIC_PACKET_BUFFER_NUM)
#if BUFFER_PACKET_SIZE
int buffer_mic_enc[BUFFER_PACKET_SIZE];
#endif
#endif
u8 buffer_mic_pkt_wptr;
u8 buffer_mic_pkt_rptr;
#if TL_NOISE_SUPRESSION_ENABLE
int md_long =0;
int md_short =0;
int md_im =0;
int md_noise = 0;
int md_gain = 256;
#endif
#if (IIR_FILTER_ENABLE)
//inner band EQ default parameter. user need to set according to actual situation.
//int filter_1[10] = {16630, -22724, 15507, 22724, -15753};
//int filter_2[10] = {15380, 0, 14450, 0, -13446};
//int filter_3[10] = {14961, 14869, 0, -13446, 0};
int filter_1[10] = {995*4, 1990*4, 995*4, 849*4, 734*4};
int filter_2[10] = {3691*4, -5564*4, 2915*4, 5564*4, -2510*4};
int filter_3[10] = {2534*4, -1482*4, 955*4, 3956*4, -1866*4};
u8 filter1_shift = 0;
u8 filter2_shift = 0;
u8 filter3_shift = 0;
//used for OOB processing. i.e LPF. user need to set according to actual situation
int LPF_FILTER_1[10] = {739,87,739,2419,-1401};
int LPF_FILTER_2[10] = {4301,5262,4299,889,-3601};
u8 lpf_filter1_shift = 0;
u8 lpf_filter2_shift = 0;
//voice data out of band need to be processed using 12 bits.
_attribute_ram_code_ void voice_iir_OOB(signed short * ps, signed short *pd, int* coef, int nsample,u8 shift)
{
int i = 0;
long int s = 0;
for (i=0; i<nsample; i++)
{
//s = (*ps * coef[0])>>shift;
s = (*ps * coef[0])>>0; //input 16-bit
s += coef[5] * coef[1];
s += coef[6] * coef[2]; //coef 0,1,2: 12-bit
s += coef[7] * coef[3];
s += coef[8] * coef[4]; //coef 4 & 5: 10-bit; coef 7 & 8: 18-bit
//s = s >> 10; //18-bit
//s = s >> 12; //18-bit
s = ((s + (1 << 11)) >> 12); /////this line code indicate that process sample data with 12 bits
#if 0
if (s >= (1<<18))
s = (1<<18) - 1;
else if (s < -(1<<18))
s = - (1<<18);
#endif
coef[6] = coef[5]; //16-bit
coef[5] = *ps++; //16-bit
coef[8] = coef[7]; //18-bit
coef[7] = s;
//*pd++ = s >> 3;
//*pd++ = s >> 1;
//limit
if(s > 32767){
s = 32767;
}
else if(s < -32767){
s = -32767;
}
*pd++ = s >> shift;
}
}
_attribute_ram_code_ static inline void audio_getHalfsample_func(s16*ps, u16 len)
{
for(u16 i = 0;i < (len >> 1);i++)
{
ps[i] = ps[2 * i];
}
}
//voice data inner band need to be processed using 14 bits.
_attribute_ram_code_ void voice_iir(signed short * ps, signed short *pd, int* coef, int nsample,u8 shift)
{
int i = 0;
long int s = 0;
for (i=0; i<nsample; i++)
{
//s = (*ps * coef[0])>>shift;
s = (*ps * coef[0])>>0; //input 16-bit
s += coef[5] * coef[1];
s += coef[6] * coef[2]; //coef 0,1,2: 12-bit
s += coef[7] * coef[3];
s += coef[8] * coef[4]; //coef 4 & 5: 10-bit; coef 7 & 8: 18-bit
//s = s >> 10; //18-bit
//s = s >> 12; //18-bit
s = ((s + (1 << 13)) >> 14); /////this line code indicate that process sample data with 14 bits
// s = ((s + (1 << 11)) >> 12);
#if 0
if (s >= (1<<18))
s = (1<<18) - 1;
else if (s < -(1<<18))
s = - (1<<18);
#endif
coef[6] = coef[5]; //16-bit
coef[5] = *ps++; //16-bit
coef[8] = coef[7]; //18-bit
coef[7] = s;
//*pd++ = s >> 3;
//*pd++ = s >> 1;
//limit
if(s > 32767){
s = 32767;
}
else if(s < -32767){
s = -32767;
}
*pd++ = s >> shift;
}
}
void Audio_VolumeSet(unsigned char input_output_select,unsigned char volume_set_value)
{
#if 0 //not support now
#if (BLE_DMIC_ENABLE)
reg_mic_ctrl = MASK_VAL( FLD_AUD_MIC_VOL_CONTROL, (volume_set_value & 0x3f),\
FLD_AUD_MIC_MONO_EN, 1, \
FLD_AUD_AMIC_DMIC_SELECT, 1 );
#else
reg_mic_ctrl = MASK_VAL( FLD_AUD_MIC_VOL_CONTROL, (volume_set_value & 0x3f),\
FLD_AUD_MIC_MONO_EN, 1, \
FLD_AUD_AMIC_DMIC_SELECT, 0 );
#endif
#endif
}
#define IIR_FILTER_ADR 0x71000
#define CBUFFER_SIZE 20
u8 filter_step_enable = 0;
u8 vol_gain_tmp = 0xff;
u8 pga_post_gain_tmp = 0xff;
u8 filter_cmp[20];
/*
FLASH 0x71000
+----------------0x71000
| c1(20B) first inner band EQ
+----------------0x71013
| c2(20B) second inner band EQ
+----------------0x71027
| c3(20B) three inner band EQ
+----------------0x7103B
| c4(20B) first out of band EQ
+----------------0x7104F
| c5(20B) second out of band EQ
+----------------0x71063
| f1_sft(1B) | f2_sft(1B) |f3_sft(1B) |f4_sft(1B) | f5_sft(1B) five shift
+----------------0x7109F
+----------------0x710A0
| vol_gain(1B)volume gain setting
+----------------0x710A1
| PGA_POST_GAIN(1B)(0~49): 0x710A1
+----------------0x710A2
*/
#define MANUAL_VOLUMN_SETTINGS 0x1C
void filter_setting()
{
//get the configuration data in the flash
u32 *pfilter = (u32*)IIR_FILTER_ADR;
u8 *p_start_iir = (u8 *)(pfilter);
memset(filter_cmp, 0xff,sizeof(filter_cmp));
if(memcmp(p_start_iir,filter_cmp,sizeof(filter_cmp)))//step 1 disaptch
{
memcpy((u8 *)filter_1,p_start_iir,CBUFFER_SIZE);
filter_step_enable |= BIT(1);
memset(filter_cmp, 0xff,sizeof(filter_cmp));
}
if(memcmp(p_start_iir+CBUFFER_SIZE,filter_cmp,sizeof(filter_cmp)))//step 2 disaptch
{
memcpy((u8 *)filter_2,p_start_iir+CBUFFER_SIZE,CBUFFER_SIZE);
filter_step_enable |= BIT(2);
memset(filter_cmp, 0xff,sizeof(filter_cmp));
}
if(memcmp(p_start_iir+(CBUFFER_SIZE*2),filter_cmp,sizeof(filter_cmp)))//step 3 dispatch
{
memcpy((u8 *)filter_3,p_start_iir+(CBUFFER_SIZE*2),CBUFFER_SIZE);
filter_step_enable |= BIT(3);
memset(filter_cmp, 0xff,sizeof(filter_cmp));
}
if(memcmp(p_start_iir+(CBUFFER_SIZE*3),filter_cmp,sizeof(filter_cmp)))//step 4 dispatch
{
memcpy((u8 *)LPF_FILTER_1,p_start_iir+(CBUFFER_SIZE*3),CBUFFER_SIZE);
filter_step_enable |= BIT(4);
memset(filter_cmp, 0xff,sizeof(filter_cmp));
}
if(memcmp(p_start_iir+(CBUFFER_SIZE*4),filter_cmp,sizeof(filter_cmp)))//step 5 dispatch
{
memcpy((u8 *)LPF_FILTER_2,p_start_iir+(CBUFFER_SIZE*4),CBUFFER_SIZE);
filter_step_enable |= BIT(5);
memset(filter_cmp, 0xff,sizeof(filter_cmp));
}
int i;
i = CBUFFER_SIZE*5;
filter1_shift = (p_start_iir[i] == 0xff) ? 0:p_start_iir[i];
filter2_shift = (p_start_iir[i+1] == 0xff) ? 0:p_start_iir[i+1];
filter3_shift = (p_start_iir[i+2] == 0xff) ? 0:p_start_iir[i+2];
lpf_filter1_shift = (p_start_iir[i+3] == 0xff)? 0:p_start_iir[i+3];
lpf_filter2_shift = (p_start_iir[i+4] == 0xff)? 0:p_start_iir[i+4];
//volume gain setting .position 0x710A0
vol_gain_tmp = p_start_iir[0xA0];
if(vol_gain_tmp!=0xff){
if(vol_gain_tmp&0x80){
if(MANUAL_VOLUMN_SETTINGS<(vol_gain_tmp&0x7f)){
return;
}
Audio_VolumeSet(1,MANUAL_VOLUMN_SETTINGS-(vol_gain_tmp&0x7f));
}else{
if(MANUAL_VOLUMN_SETTINGS+vol_gain_tmp>0x3f){
return;
}
Audio_VolumeSet(1,MANUAL_VOLUMN_SETTINGS+vol_gain_tmp);
}
}else{
Audio_VolumeSet(1,MANUAL_VOLUMN_SETTINGS);
}
//PGA_POST_GAIN setting .position 0x710A1
#if (!BLE_DMIC_ENABLE)
pga_post_gain_tmp = p_start_iir[0xA1];
if(pga_post_gain_tmp != 0xff){
if(pga_post_gain_tmp > 0x0f){//0x0f: PGA_GAIN_VOL_0_0DB
return;
}
analog_write_reg8(codec_ana_cfg4,(analog_read(codec_ana_cfg4) & 0x00) | pga_post_gain_tmp);
}
#endif
return ;
}
#endif
#if (TL_AUDIO_MODE == TL_AUDIO_RCU_ADPCM_GATT_TLEINK) //RCU,GATT Telink
void proc_mic_encoder (void)
{
static u16 buffer_mic_rptr;
u16 mic_wptr = (audio_get_rx_dma_wptr (DMA2) - (u32)buffer_mic) >> 1;
u16 l = (mic_wptr >= buffer_mic_rptr) ? (mic_wptr - buffer_mic_rptr) : 0xffff;
if (l >=(TL_MIC_BUFFER_SIZE>>2)) {
s16 *ps = buffer_mic + buffer_mic_rptr;
#if TL_NOISE_SUPRESSION_ENABLE
// for FIR adc sample data, only half part data are effective
for (int i=0; i<TL_MIC_ADPCM_UNIT_SIZE*2; i++) {
ps[i] = noise_supression (ps[i]);
}
#endif
#if (IIR_FILTER_ENABLE)
#if 0
//step1: out of band voice 12bits EQ filter process
voice_iir_OOB(ps, ps, LPF_FILTER_1, (TL_MIC_BUFFER_SIZE>>2), lpf_filter1_shift);//12 bits
voice_iir_OOB(ps, ps, LPF_FILTER_2, (TL_MIC_BUFFER_SIZE>>2), lpf_filter2_shift);//12 bits
//step2: 32K->16K
audio_getHalfsample_func(ps, TL_MIC_BUFFER_SIZE>>2); //496B/2=> 248B
//step3: inner band voice 14bits EQ filter process
voice_iir(ps,ps,filter_1,(TL_MIC_BUFFER_SIZE>>3),filter1_shift);//14 bits
voice_iir(ps,ps,filter_2,(TL_MIC_BUFFER_SIZE>>3),filter2_shift);//14 bits
voice_iir(ps,ps,filter_3,(TL_MIC_BUFFER_SIZE>>3),filter3_shift);//14 bits
#endif
#if 0
//step1: out of band voice 12bits EQ filter process
if((filter_step_enable & 0x30) != 0)
{
if(filter_step_enable & BIT(4))
{
voice_iir_OOB(ps, ps, LPF_FILTER_1, (TL_MIC_BUFFER_SIZE>>2), lpf_filter1_shift);//12 bits
}
if(filter_step_enable & BIT(5))
{
voice_iir_OOB(ps, ps, LPF_FILTER_2, (TL_MIC_BUFFER_SIZE>>2), lpf_filter2_shift);//12 bits
}
}
//step2: 32K->16K
audio_getHalfsample_func(ps, TL_MIC_BUFFER_SIZE>>2); //496B/2=> 248B
#endif
//step3: inner band voice 14bits EQ filter process
if((filter_step_enable & 0x0e) != 0)
{
if(filter_step_enable & BIT(1))
{
voice_iir(ps,ps,filter_1,(TL_MIC_BUFFER_SIZE>>2),filter1_shift);//14 bits
}
if(filter_step_enable & BIT(2))
{
voice_iir(ps,ps,filter_2,(TL_MIC_BUFFER_SIZE>>2),filter2_shift);//14 bits
}
if(filter_step_enable & BIT(3))
{
voice_iir(ps,ps,filter_3,(TL_MIC_BUFFER_SIZE>>2),filter3_shift);//14 bits
}
}
// step4: Soft HPF, NONE need
#endif
mic_to_adpcm_split ( ps, TL_MIC_ADPCM_UNIT_SIZE,
(s16 *)(buffer_mic_enc + (ADPCM_PACKET_LEN>>2) *
(buffer_mic_pkt_wptr & (TL_MIC_PACKET_BUFFER_NUM - 1))), 1);
buffer_mic_rptr = buffer_mic_rptr ? 0 : (TL_MIC_BUFFER_SIZE>>2);
buffer_mic_pkt_wptr++;
int pkts = (buffer_mic_pkt_wptr - buffer_mic_pkt_rptr) & (TL_MIC_PACKET_BUFFER_NUM*2-1);
if (pkts > TL_MIC_PACKET_BUFFER_NUM) {
buffer_mic_pkt_rptr++;
}
}
}
int * mic_encoder_data_buffer ()
{
if (buffer_mic_pkt_rptr == buffer_mic_pkt_wptr) {
return 0;
}
int *ps = buffer_mic_enc + (ADPCM_PACKET_LEN>>2) *
(buffer_mic_pkt_rptr & (TL_MIC_PACKET_BUFFER_NUM - 1));
return ps;
}
void mic_encoder_data_read_ok (void)
{
buffer_mic_pkt_rptr++;
}
#endif
#elif (TL_AUDIO_MODE & DONGLE_PROJECT) //Dongle
#if (TL_AUDIO_MODE == TL_AUDIO_DONGLE_ADPCM_GATT_TELINK) //Dongle, GATT Telink
u8 abuf_mic_wptr, abuf_dec_wptr;
u16 abuf_dec_rptr;
#define DEC_BUFFER_SIZE (MIC_SHORT_DEC_SIZE<<2)
#define PACK_POINTER (abuf_dec_rptr/248) | (abuf_dec_wptr<<8) | (abuf_mic_wptr<<16)
#define USB_ISO_IN_SIZE (MIC_SAMPLE_RATE / 1000)
u8 abuf_mic[MIC_ADPCM_FRAME_SIZE * 4];
s16 abuf_dec[DEC_BUFFER_SIZE];
int abuf_reset = 0;
void abuf_init ()
{
abuf_mic_wptr = abuf_dec_wptr = 0;
abuf_reset = 16;
}
void abuf_mic_add (u32 *p)
{
u32 *pd = (u32 *) (abuf_mic + (abuf_mic_wptr & 3) * MIC_ADPCM_FRAME_SIZE);
for (int i=0; i<(MIC_ADPCM_FRAME_SIZE>>2); i++)
{
*pd ++ = *p++;
}
abuf_mic_wptr ++;
}
void abuf_mic_dec ()
{
static int start = 1;
static int abuf_reset_no;
if (abuf_reset)
{
abuf_dec_wptr = abuf_mic_wptr;
}
else
{
u8 num_mic = abuf_mic_wptr - abuf_dec_wptr;
u8 num_dec = abuf_dec_wptr - (abuf_dec_rptr/MIC_SHORT_DEC_SIZE);
if (num_mic > 4) // in case of overflow
{
abuf_dec_wptr ++;
}
if (num_dec > 4)
{
abuf_reset = 16;
start = 1;
abuf_reset_no++;
}
else if ( ((!start && num_mic>=1) || (start && num_mic>=2)) && (num_dec <= 3) )
{
adpcm_to_pcm (
(s16 *) (abuf_mic + (abuf_dec_wptr & 3) * MIC_ADPCM_FRAME_SIZE),
abuf_dec + (abuf_dec_wptr & 3) * MIC_SHORT_DEC_SIZE,
MIC_SHORT_DEC_SIZE );
abuf_dec_wptr ++; // 256-byte = 128-s16
start = 0;
}
}
}
_attribute_ram_code_ void abuf_dec_usb ()
{
static u32 tick_usb_iso_in;
static u8 buffer_empty = 1;
static u8 n_usb_iso = 0;
n_usb_iso++;
if (clock_time_exceed (tick_usb_iso_in, 4000))
{
abuf_reset = 16;
}
tick_usb_iso_in = clock_time ();
if (abuf_reset)
{
abuf_dec_rptr = abuf_dec_wptr*MIC_SHORT_DEC_SIZE;
abuf_reset--;
}
/////////////////// copy data to usb iso in buffer ///////////////
reg_usb_ep7_ptr = 0;
u8 num = abuf_dec_wptr - (abuf_dec_rptr/MIC_SHORT_DEC_SIZE);
if (num)
{
if ( (buffer_empty && num >= 3) || (!buffer_empty && (num >= 1 || (n_usb_iso & 3))) )
{
buffer_empty = 0;
u16 offset = abuf_dec_rptr%DEC_BUFFER_SIZE;
s16 *ps = abuf_dec + offset;
if(offset == DEC_BUFFER_SIZE - (USB_ISO_IN_SIZE/2)){
for (int i=0; i<(USB_ISO_IN_SIZE/2); i++)
{
reg_usb_ep7_dat = *ps;
reg_usb_ep7_dat = *ps++ >> 8;
}
ps = abuf_dec;
for (int i=0; i<(USB_ISO_IN_SIZE/2); i++)
{
reg_usb_ep7_dat = *ps;
reg_usb_ep7_dat = *ps++ >> 8;
}
}
else{
for (int i=0; i<USB_ISO_IN_SIZE; i++)
{
reg_usb_ep7_dat = *ps;
reg_usb_ep7_dat = *ps++ >> 8;
}
}
abuf_dec_rptr += USB_ISO_IN_SIZE;
if(abuf_dec_rptr >= (MIC_SHORT_DEC_SIZE<<8) ){
abuf_dec_rptr = 0;
}
}
else
{
for (int i=0; i<USB_ISO_IN_SIZE * 2; i++)
{
reg_usb_ep7_dat = 0;
}
}
}
else
{
for (int i=0; i<USB_ISO_IN_SIZE * 2; i++)
{
reg_usb_ep7_dat = 0;
}
buffer_empty = 1;
}
reg_usb_ep7_ctrl = BIT(0); //ACK iso in
}
#endif
#endif
+123
View File
@@ -0,0 +1,123 @@
/********************************************************************************************************
* @file tl_audio.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#ifndef TL_AUDIO_H_
#define TL_AUDIO_H_
#include "tl_common.h"
#include "audio_config.h"
#if (TL_AUDIO_MODE & RCU_PROJECT) //RCU
#ifndef TL_NOISE_SUPRESSION_ENABLE
#define TL_NOISE_SUPRESSION_ENABLE 0
#endif
#ifndef IIR_FILTER_ENABLE
#define IIR_FILTER_ENABLE 0
#endif
#ifndef TL_MIC_PACKET_BUFFER_NUM
#define TL_MIC_PACKET_BUFFER_NUM 4
#endif
#ifndef MIC_SHORT_DEC_SIZE
#define MIC_SHORT_DEC_SIZE 0
#endif
#ifndef ADPCM_PACKET_LEN
#define ADPCM_PACKET_LEN 0
#endif
#ifndef TL_MIC_ADPCM_UNIT_SIZE
#define TL_MIC_ADPCM_UNIT_SIZE 0
#endif
#ifndef TL_MIC_BUFFER_SIZE
#define TL_MIC_BUFFER_SIZE 0
#endif
#if TL_MIC_BUFFER_SIZE
s16 buffer_mic[TL_MIC_BUFFER_SIZE>>1] __attribute__((aligned(4)));
#endif
#if TL_NOISE_SUPRESSION_ENABLE
extern int md_long;
extern int md_short;
extern int md_im;
extern int md_noise;
extern int md_gain;
static inline int noise_supression (s16 md) {
static int md_th =384;
//static int md_long =0;
//static int md_short =0;
//static int md_im =0;
//static int md_noise = 0;
//static int md_gain = 256;
md_long = ((md_long * 1023) + abs (md)) >> 10;
md_short = ((md_short * 127) + abs (md)) >> 7;
md_im = ((md_im * 15) + abs (md)) >> 4;
//md_long = ((md_long * 127) + abs (md)) >> 7;
//md_short = ((md_short * 31) + abs (md)) >> 5;
//md_im = ((md_im * 3) + abs (md)) >> 2;
if ((md_noise && (md_short > md_th)) || (md_im > (md_th<<1))) {
md_noise = 0;
md_long = md_short << 2;
}
else if (!md_noise && md_long < md_th) {
md_noise = 1;
}
if (md_noise) {
if (md_gain) { md_gain --; }
}
else {
if (md_gain < 256) { md_gain ++;}
}
return (md * md_gain + 128) >> 8;
}
#endif
void voice_iir_OOB(signed short * ps, signed short *pd, int* coef, int nsample,u8 shift);
void voice_iir(signed short * ps, signed short *pd, int* coef, int nsample,u8 shift);
void Audio_VolumeSet(unsigned char input_output_select,unsigned char volume_set_value);
void filter_setting();
void audio_mic_param_init(void);
void proc_mic_encoder (void);
int * mic_encoder_data_buffer ();
void mic_encoder_data_read_ok (void);
#elif (TL_AUDIO_MODE & DONGLE_PROJECT) //Dongle
void abuf_init ();
void abuf_mic_add (u32 *p);
void abuf_mic_dec ();
void abuf_dec_usb ();
#endif
#endif /* TL_AUDIO_H_ */
+509
View File
@@ -0,0 +1,509 @@
/********************************************************************************************************
* @file keyboard.c
*
* @brief This is the source file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#include "tl_common.h"
#include "drivers.h"
#include "keyboard.h"
#include "application/usbstd/usbkeycode.h"
#if (defined(KB_DRIVE_PINS) && defined(KB_SCAN_PINS))
const u32 drive_pins[] = KB_DRIVE_PINS;
const u32 scan_pins[] = KB_SCAN_PINS;
#if (STUCK_KEY_PROCESS_ENABLE)
unsigned char stuckKeyPress[ARRAY_SIZE(drive_pins)];
#endif
_attribute_data_retention_ kb_data_t kb_event;
_attribute_data_retention_ kb_data_t kb_event_cache;
_attribute_data_retention_ unsigned char deepback_key_state;
_attribute_data_retention_ u32 deepback_key_tick;
#ifndef SCAN_PIN_50K_PULLUP_ENABLE
#define SCAN_PIN_50K_PULLUP_ENABLE 0
#endif
#ifndef KB_MAP_DEFAULT
#define KB_MAP_DEFAULT 1
#endif
#ifndef KB_LINE_MODE
#define KB_LINE_MODE 0
#endif
#ifndef KB_LINE_HIGH_VALID
#define KB_LINE_HIGH_VALID 1
#endif
#ifndef KB_KEY_FLASH_PIN_MULTI_USE
#define KB_KEY_FLASH_PIN_MULTI_USE 0
#endif
#ifndef KB_HAS_CTRL_KEYS
#define KB_HAS_CTRL_KEYS 1
#endif
#ifndef KB_RM_GHOST_KEY_EN
#define KB_RM_GHOST_KEY_EN 0
#endif
#ifndef KB_HAS_FN_KEY
#define KB_HAS_FN_KEY 1
#endif
#ifndef KB_DRV_DELAY_TIME
#define KB_DRV_DELAY_TIME 10
#endif
#ifndef KB_STANDARD_KEYBOARD
#define KB_STANDARD_KEYBOARD 0
#endif
#if KB_REPEAT_KEY_ENABLE
#ifndef KB_REPEAT_KEY_INTERVAL_MS
#define KB_REPEAT_KEY_INTERVAL_MS 200
#endif
#ifndef KB_REPEAT_KEY_NUM
#define KB_REPEAT_KEY_NUM 4
#endif
static const unsigned char kb_map_repeat[KB_REPEAT_KEY_NUM] = KB_MAP_REPEAT;
repeatKey_t repeat_key = {
0,
0,
0,
0,
U32_MAX,
};
#endif
typedef unsigned char kb_k_mp_t[ARRAY_SIZE(drive_pins)]; //typedef unsigned char kb_k_mp_t[8]
#if KB_MAP_DEFAULT
#ifndef KB_MAP_NORMAL
static const unsigned char kb_map_normal[ARRAY_SIZE(scan_pins)][ARRAY_SIZE(drive_pins)] = {
{VK_PAUSE, VK_POWER, VK_EURO, VK_SLEEP, VK_RCTRL, VK_WAKEUP, VK_CTRL, VK_F5},
{VK_Q, VK_TAB, VK_A, VK_ESC, VK_Z, VK_NCHG, VK_TILDE, VK_1},
{VK_W, VK_CAPITAL, VK_S, VK_K45, VK_X, VK_CHG, VK_F1, VK_2},
{VK_E, VK_F3, VK_D, VK_F4, VK_C, VK_ROMA, VK_F2, VK_3},
{VK_R, VK_T, VK_F, VK_G, VK_V, VK_B, VK_5, VK_4},
{VK_U, VK_Y, VK_J, VK_H, VK_M, VK_N, VK_6, VK_7},
{VK_I, VK_RBRACE, VK_K, VK_F6, VK_COMMA, VK_K56, VK_EQUAL, VK_8},
{VK_O, VK_F7, VK_L, VK_RMB, VK_PERIOD, VK_APP, VK_F8, VK_9},
{VK_P, VK_LBRACE, VK_SEMICOLON, VK_QUOTE, VK_BACKSLASH, VK_SLASH, VK_MINUS, VK_0},
{VK_SCR_LOCK,VK_C9R1, VK_FN, VK_ALT, VK_MMODE, VK_RALT, VK_C9R6, VK_PRINTSCREEN},
{VK_K14, VK_BACKSPACE,VK_BACKSLASH, VK_F11, VK_ENTER, VK_F12, VK_F9, VK_F10},
{VK_HOME, VK_LEFT, VK_END, VK_SPACE, VK_NUM_LOCK, VK_DOWN, VK_DELETE, VK_POWER},
{VK_UP, VK_NONE, VK_DOWN, VK_INSERT, VKPAD_SLASH, VK_RIGHT, VK_INSERT, VK_SLEEP},
{VK_PAGE_UP, VK_RIGHT, VK_PAGE_DOWN, VKPAD_PERIOD, VKPAD_ASTERIX,VKPAD_MINUS, VK_PAGE_UP, VK_PAGE_DOWN},
{VKPAD_PLUS, VK_K107, VKPAD_ENTER, VK_UP, VK_PLAY_PAUSE,VK_LEFT, VK_HOME, VK_END},
{VK_WAKEUP, VK_SHIFT, VK_RSHIFT, VK_VOL_DN, VK_VOL_UP, VK_NEXT_TRK, VK_PREV_TRK, VK_MEDIA},
{VK_MAIL, VK_WIN, VK_W_FORWRD, VK_W_STOP, VK_W_BACK, VK_W_REFRESH, VK_W_MUTE, VK_W_SRCH},
{VK_KCL, VK_W_FAV, VK_RWIN, VK_MY_COMP, VK_STOP, VK_CAL, VK_WEB, VK_KCR},
};
#else
static const unsigned char kb_map_normal[ARRAY_SIZE(scan_pins)][ARRAY_SIZE(drive_pins)] = KB_MAP_NORMAL;
#endif
#if (KB_STANDARD_KEYBOARD)
#ifndef KB_MAP_NUM
static const unsigned char kb_map_num[ARRAY_SIZE(scan_pins)][ARRAY_SIZE(drive_pins)] = {
{VK_PAUSE, VK_POWER, VK_EURO, VK_SLEEP, VK_RCTRL, VK_WAKEUP, VK_CTRL, VK_F5},
{VK_Q, VK_TAB, VK_A, VK_ESC, VK_Z, VK_NCHG, VK_TILDE, VK_1},
{VK_W, VK_CAPITAL, VK_S, VK_K45, VK_X, VK_CHG, VK_F1, VK_2},
{VK_E, VK_F3, VK_D, VK_F4, VK_C, VK_ROMA, VK_F2, VK_3},
{VK_R, VK_T, VK_F, VK_G, VK_V, VK_B, VK_5, VK_4},
{VK_U, VK_Y, VK_J, VK_H, VK_M, VK_N, VK_6, VK_7},
{VK_I, VK_RBRACE, VK_K, VK_F6, VK_COMMA, VK_K56, VK_EQUAL, VK_8},
{VK_O, VK_F7, VK_L, VK_RMB, VK_PERIOD, VK_APP, VK_F8, VK_9},
{VK_P, VK_LBRACE, VK_SEMICOLON, VK_QUOTE, VK_BACKSLASH, VK_SLASH, VK_MINUS, VK_0},
{VK_SCR_LOCK,VK_C9R1, VK_FN, VK_ALT, VK_MMODE, VK_RALT, VK_C9R6, VK_PRINTSCREEN},
{VK_K14, VK_BACKSPACE,VK_BACKSLASH, VK_F11, VK_ENTER, VK_F12, VK_F9, VK_F10},
{VKPAD_7, VKPAD_4, VKPAD_1, VK_SPACE, VK_NUM_LOCK, VK_DOWN, VK_DELETE, VK_POWER},
{VKPAD_8, VKPAD_5, VKPAD_2, VKPAD_0, VKPAD_SLASH, VK_RIGHT, VK_INSERT, VK_SLEEP},
{VKPAD_9, VKPAD_6, VKPAD_3, VKPAD_PERIOD, VKPAD_ASTERIX,VKPAD_MINUS, VK_PAGE_UP, VK_PAGE_DOWN},
{VKPAD_PLUS, VK_K107, VKPAD_ENTER, VK_UP, VK_PLAY_PAUSE,VK_LEFT, VK_HOME, VK_END},
{VK_WAKEUP, VK_SHIFT, VK_RSHIFT, VK_VOL_DN, VK_VOL_UP, VK_NEXT_TRK, VK_PREV_TRK, VK_MEDIA},
{VK_MAIL, VK_WIN, VK_W_FORWRD, VK_W_STOP, VK_W_BACK, VK_W_REFRESH, VK_W_MUTE, VK_W_SRCH},
{VK_KCL, VK_W_FAV, VK_RWIN, VK_MY_COMP, VK_STOP, VK_CAL, VK_WEB, VK_KCR},
};
#else
static const unsigned char kb_map_num[ARRAY_SIZE(scan_pins)][ARRAY_SIZE(drive_pins)] = KB_MAP_NUM;
#endif
#ifndef KB_MAP_FN
static const unsigned char kb_map_fn[ARRAY_SIZE(scan_pins)][ARRAY_SIZE(drive_pins)] = {
{VK_PAUSE, VK_POWER, VK_EURO, VK_SLEEP, VK_RCTRL, VK_WAKEUP, VK_CTRL, VK_F5},
{VK_Q, VK_TAB, VK_A, VK_ESC, VK_Z, VK_NCHG, VK_TILDE, VK_1},
{VK_W, VK_CAPITAL, VK_S, VK_K45, VK_X, VK_CHG, VK_F1, VK_2},
{VK_E, VK_F3, VK_D, VK_F4, VK_C, VK_ROMA, VK_F2, VK_3},
{VK_R, VK_T, VK_F, VK_G, VK_V, VK_B, VK_5, VK_4},
{VK_U, VK_Y, VK_J, VK_H, VK_M, VK_N, VK_6, VK_7},
{VK_I, VK_RBRACE, VK_K, VK_F6, VK_COMMA, VK_K56, VK_EQUAL, VK_8},
{VK_O, VK_F7, VK_L, VK_RMB, VK_PERIOD, VK_APP, VK_F8, VK_9},
{VK_P, VK_LBRACE, VK_SEMICOLON, VK_QUOTE, VK_BACKSLASH, VK_SLASH, VK_MINUS, VK_0},
{VK_SCR_LOCK,VK_C9R1, VK_FN, VK_ALT, VK_MMODE, VK_RALT, VK_C9R6, VK_PRINTSCREEN},
{VK_K14, VK_BACKSPACE,VK_BACKSLASH, VK_F11, VK_ENTER, VK_F12, VK_F9, VK_F10},
{VKPAD_7, VKPAD_4, VKPAD_1, VK_SPACE, VK_NUM_LOCK, VK_DOWN, VK_DELETE, VK_POWER},
{VKPAD_8, VKPAD_5, VKPAD_2, VKPAD_0, VKPAD_SLASH, VK_RIGHT, VK_INSERT, VK_SLEEP},
{VKPAD_9, VKPAD_6, VKPAD_3, VKPAD_PERIOD, VKPAD_ASTERIX,VKPAD_MINUS, VK_PAGE_UP, VK_PAGE_DOWN},
{VKPAD_PLUS, VK_K107, VKPAD_ENTER, VK_UP, VK_PLAY_PAUSE,VK_LEFT, VK_HOME, VK_END},
{VK_WAKEUP, VK_SHIFT, VK_RSHIFT, VK_VOL_DN, VK_VOL_UP, VK_NEXT_TRK, VK_PREV_TRK, VK_MEDIA},
{VK_MAIL, VK_WIN, VK_W_FORWRD, VK_W_STOP, VK_W_BACK, VK_W_REFRESH, VK_W_MUTE, VK_W_SRCH},
{VK_KCL, VK_W_FAV, VK_RWIN, VK_MY_COMP, VK_STOP, VK_CAL, VK_WEB, VK_KCR},
};
#else
static const unsigned char kb_map_fn[ARRAY_SIZE(scan_pins)][ARRAY_SIZE(drive_pins)] = KB_MAP_FN;
#endif
kb_k_mp_t * kb_p_map[4] = {
kb_map_normal,
kb_map_num,
kb_map_fn,
kb_map_fn,
};
#endif
///////////////////////////////////////////////////////////////////////
//////////// load configuration from flash/OTP ////////////////////////
///////////////////////////////////////////////////////////////////////
#else //line 62
#endif
_attribute_data_retention_ u32 scan_pin_need;
static unsigned char kb_is_fn_pressed = 0;
kb_k_mp_t * kb_k_mp;
void kb_rmv_ghost_key(u32 * pressed_matrix){
u32 mix_final = 0;
foreach_arr(i, drive_pins){
for(int j = (i+1); j < ARRAY_SIZE(drive_pins); ++j){
u32 mix = (pressed_matrix[i] & pressed_matrix[j]);
//four or three key at "#" is pressed at the same time, should remove ghost key
if( mix && (!BIT_IS_POW2(mix) || (pressed_matrix[i] ^ pressed_matrix[j])) ){
// remove ghost keys
//pressed_matrix[i] &= ~mix;
//pressed_matrix[j] &= ~mix;
mix_final |= mix;
}
}
pressed_matrix[i] &= ~mix_final;
}
}
#if (LONG_PRESS_KEY_POWER_OPTIMIZE)
int key_matrix_same_as_last_cnt = 0; //record key matrix no change cnt
#endif
unsigned int key_debounce_filter( u32 mtrx_cur[], u32 filt_en ){
u32 kc = 0;
#if (LONG_PRESS_KEY_POWER_OPTIMIZE)
unsigned char matrix_differ = 0;
#endif
static u32 mtrx_pre[ARRAY_SIZE(drive_pins)];
static u32 mtrx_last[ARRAY_SIZE(drive_pins)];
foreach_arr(i, drive_pins){
u32 mtrx_tmp = mtrx_cur[i];
#if (STUCK_KEY_PROCESS_ENABLE)
stuckKeyPress[i] = mtrx_tmp ? 1 : 0;
#endif
if( filt_en ){
//mtrx_cur[i] = (mtrx_last[i] ^ mtrx_tmp) ^ (mtrx_last[i] | mtrx_tmp); //key_matrix_pressed is valid when current and last value is the same
mtrx_cur[i] = ( ~mtrx_last[i] & (mtrx_pre[i] & mtrx_tmp) ) | ( mtrx_last[i] & (mtrx_pre[i] | mtrx_tmp) );
}
if ( mtrx_cur[i] != mtrx_last[i] ) {
kc = 1;
}
#if (LONG_PRESS_KEY_POWER_OPTIMIZE)
if(mtrx_cur[i]^mtrx_pre[i]){ //when same, XOR value is 0
matrix_differ = 1;
}
#endif
mtrx_pre[i] = mtrx_tmp;
mtrx_last[i] = mtrx_cur[i];
}
#if (LONG_PRESS_KEY_POWER_OPTIMIZE)
if(matrix_differ){
key_matrix_same_as_last_cnt = 0;
}
else{
key_matrix_same_as_last_cnt++;
}
#endif
return kc;
}
// input: pressed_matrix,
// key_code: output keys array
// key_max: max keys should be returned
static inline void kb_remap_key_row(int drv_ind, u32 m, int key_max, kb_data_t *kb_data){
foreach_arr(i, scan_pins){
if(m & 0x01){
unsigned char kc = kb_k_mp[i][drv_ind];
#if(KB_HAS_CTRL_KEYS)
if(kc >= VK_CTRL && kc <= VK_RWIN)
kb_data->ctrl_key |= BIT(kc - VK_CTRL);
//else if(kc == VK_MEDIA_END)
//lock_button_pressed = 1;
else if(VK_ZOOM_IN == kc || VK_ZOOM_OUT == kc){
kb_data->ctrl_key |= VK_MSK_LCTRL;
kb_data->keycode[kb_data->cnt++] = (VK_ZOOM_IN == kc)? VK_EQUAL : VK_MINUS;
}
else if(kc != VK_FN)//fix fn ghost bug
kb_data->keycode[kb_data->cnt++] = kc;
#else
kb_data->keycode[kb_data->cnt++] = kc;
#endif
if(kb_data->cnt >= key_max){
break;
}
}
m = m >> 1;
if(!m){
break;
}
}
}
static inline void kb_remap_key_code(u32 * pressed_matrix, int key_max, kb_data_t *kb_data, int numlock_status){
#if (KB_STANDARD_KEYBOARD)
kb_k_mp = kb_p_map[(numlock_status&1) | (kb_is_fn_pressed << 1)];
#else
kb_k_mp = (kb_k_mp_t *)&kb_map_normal[0];
#endif
foreach_arr(i, drive_pins){
u32 m = pressed_matrix[i];
if(!m) continue;
kb_remap_key_row(i, m, key_max, kb_data);
if(kb_data->cnt >= key_max){
break;
}
}
}
u32 kb_scan_row(int drv_ind, unsigned char * gpio){
/*
* set as gpio mode if using spi flash pin
* */
u32 sr = irq_disable();
#if (KB_KEY_FLASH_PIN_MULTI_USE)
MSPI_AS_GPIO;
#endif
#if(!KB_LINE_MODE)
u32 drv_pin = drive_pins[drv_ind];
gpio_write(drv_pin, KB_LINE_HIGH_VALID);
gpio_set_output_en(drv_pin, 1);
#endif
u32 matrix = 0;
foreach_arr(j, scan_pins){
if(scan_pin_need & BIT(j)){
int key = !gpio_read_cache (scan_pins[j], gpio);
if(KB_LINE_HIGH_VALID != key) {
if (KB_HAS_FN_KEY && (kb_k_mp[j][drv_ind] == VK_FN)) {
kb_is_fn_pressed = 1;
}
matrix |= (1 << j);
}
}
}
//sleep_us(KB_DRV_DELAY_TIME);
gpio_read_all (gpio);
/*
* set as spi mode if using spi flash pin
* */
#if (KB_KEY_FLASH_PIN_MULTI_USE)
MSPI_AS_SPI;
#endif
#if(!KB_LINE_MODE)
//////// float drive pin ////////////////////////////
//sleep_us(KB_SCAN_DELAY_TIME);
gpio_write(drv_pin, 0);
gpio_set_output_en(drv_pin, 0);
#endif
irq_restore(sr);
return matrix;
}
u32 matrix_buff[4][ARRAY_SIZE(drive_pins)];
int matrix_wptr, matrix_rptr;
u32 kb_key_pressed(unsigned char * gpio)
{
foreach_arr(i,drive_pins){
gpio_write(drive_pins[i], KB_LINE_HIGH_VALID);
gpio_set_output_en(drive_pins[i], 1);
}
sleep_us (20);
gpio_read_all (gpio);
u32 ret = 0;
static unsigned char release_cnt = 0;
static u32 ret_last = 0;
foreach_arr(i,scan_pins){
if(KB_LINE_HIGH_VALID != !gpio_read_cache (scan_pins[i], gpio)){
ret |= (1 << i);
release_cnt = 6;
ret_last = ret;
}
//ret = ret && gpio_read(scan_pins[i]);
}
if(release_cnt){
ret = ret_last;
release_cnt--;
}
foreach_arr(i,drive_pins){
gpio_write(drive_pins[i], 0);
gpio_set_output_en(drive_pins[i], 0);
}
return ret;
}
u32 kb_scan_key_value (int numlock_status, int read_key,unsigned char * gpio)
{
kb_event.cnt = 0;
kb_event.ctrl_key = 0;
kb_is_fn_pressed = 0;
u32 pressed_matrix[ARRAY_SIZE(drive_pins)] = {0};
#if (KB_STANDARD_KEYBOARD)
kb_k_mp = kb_p_map[0];
#else
kb_k_mp = (kb_k_mp_t *)&kb_map_normal[0];
#endif
kb_scan_row (0, gpio);
for (int i=0; i<=ARRAY_SIZE(drive_pins); i++) {
u32 r = kb_scan_row (i < ARRAY_SIZE(drive_pins) ? i : 0, gpio);
if (i) {
pressed_matrix[i - 1] = r;
}
}
#if(KB_RM_GHOST_KEY_EN)
kb_rmv_ghost_key(&pressed_matrix[0]);
#endif
u32 key_changed = key_debounce_filter( pressed_matrix, \
(numlock_status & KB_NUMLOCK_STATUS_POWERON) ? 0 : 1);
#if (KB_REPEAT_KEY_ENABLE)
if(key_changed){
repeat_key.key_change_flg = KEY_CHANGE;
repeat_key.key_change_tick = clock_time();
}
else{
if(repeat_key.key_change_flg == KEY_CHANGE){
repeat_key.key_change_flg = KEY_SAME;
}
if( repeat_key.key_change_flg == KEY_SAME && repeat_key.key_repeat_flg && \
clock_time_exceed(repeat_key.key_change_tick,(KB_REPEAT_KEY_INTERVAL_MS-5)*1000)){
repeat_key.key_change_tick = clock_time();
key_changed = 1;
}
}
#endif
///////////////////////////////////////////////////////////////////
// insert buffer here
// key mapping requires NUMLOCK status
///////////////////////////////////////////////////////////////////
u32 *pd;
if (key_changed) {
/////////// push to matrix buffer /////////////////////////
pd = matrix_buff[matrix_wptr&3];
for (int k=0; k<ARRAY_SIZE(drive_pins); k++) {
*pd++ = pressed_matrix[k];
}
matrix_wptr = (matrix_wptr + 1) & 7;
if ( ((matrix_wptr - matrix_rptr) & 7) > 4 ) { //overwrite older data
matrix_rptr = (matrix_wptr - 4) & 7;
}
}
if (numlock_status & KB_NUMLOCK_STATUS_INVALID) {
return 1; //return empty key
}
////////// read out //////////
if (matrix_wptr == matrix_rptr || !read_key) {
return 0; //buffer empty, no data
}
pd = matrix_buff[matrix_rptr&3];
matrix_rptr = (matrix_rptr + 1) & 7;
///////////////////////////////////////////////////////////////////
kb_remap_key_code(pd, KB_RETURN_KEY_MAX, &kb_event, numlock_status);
#if (KB_REPEAT_KEY_ENABLE)
if(repeat_key.key_change_flg == KEY_CHANGE){
repeat_key.key_repeat_flg = 0;
if(kb_event.cnt == 1){ //handle one key repeat only
for(int i=0;i<KB_REPEAT_KEY_NUM;i++){
if(kb_event.keycode[0] == kb_map_repeat[i]){
repeat_key.key_repeat_flg = 1;
break;
}
}
}
}
#endif
return 1;
}
#endif
///////////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////////
+111
View File
@@ -0,0 +1,111 @@
/********************************************************************************************************
* @file keyboard.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include "drivers.h"
#define KB_RETURN_KEY_MAX 6
#define KB_NUMLOCK_STATUS_INVALID BIT(7)
#define KB_NUMLOCK_STATUS_POWERON BIT(15)
#define DEEPBACK_KEY_IDLE 0
#define DEEPBACK_KEY_CACHE 1 //there is deepback key cached in kb_event_cache
#define DEEPBACK_KEY_WAIT_RELEASE 2
#ifndef KB_REPEAT_KEY_ENABLE
#define KB_REPEAT_KEY_ENABLE 0
#endif
#define KEY_NONE 0
#define KEY_CHANGE 1
#define KEY_SAME 2
typedef struct{
unsigned char key_change_flg;
unsigned char key_repeat_flg;
unsigned char keycode0;
unsigned char keycode1;
unsigned int key_change_tick;
}repeatKey_t;
extern repeatKey_t repeat_key;
typedef struct{
unsigned char cnt;
unsigned char ctrl_key;
unsigned char keycode[KB_RETURN_KEY_MAX];
//unsigned char padding[2]; // for 32 bit padding, if KB_RETURN_KEY_MAX change, this should be changed
}kb_data_t;
extern kb_data_t kb_event;
extern kb_data_t kb_event_cache;
extern unsigned char deepback_key_state;
extern unsigned int deepback_key_tick;
#ifndef LONG_PRESS_KEY_POWER_OPTIMIZE
#define LONG_PRESS_KEY_POWER_OPTIMIZE 0
#endif
#ifndef STUCK_KEY_PROCESS_ENABLE
#define STUCK_KEY_PROCESS_ENABLE 0
#endif
int kb_is_data_same(kb_data_t *a, kb_data_t *b);
static inline int kb_is_key_valid(kb_data_t *p){
return (p->cnt || p->ctrl_key);
}
static inline void kb_set_key_invalid(kb_data_t *p){
p->cnt = p->ctrl_key = 0;
}
extern unsigned int kb_key_pressed(unsigned char * gpio);
extern unsigned int kb_scan_key_value (int numlock_status, int read_key,unsigned char * gpio);
extern unsigned int scan_pin_need;
static inline unsigned int kb_scan_key (int numlock_status, int read_key) {
unsigned char gpio[8];
scan_pin_need = kb_key_pressed (gpio);
if(scan_pin_need){
return kb_scan_key_value(numlock_status,read_key,gpio);
}
else{
#if (KB_REPEAT_KEY_ENABLE)
repeat_key.key_change_flg = KEY_NONE;
#endif
return 0;
}
}
+128
View File
@@ -0,0 +1,128 @@
/********************************************************************************************************
* @file printf.c
*
* @brief This is the source file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#include "tl_common.h"
#include "drivers.h"
#include "tl_common.h"
#include <stdarg.h>
#include "printf.h"
#if(DEBUG_MODE==1)
#if (DEBUG_BUS==DEBUG_USB)
__attribute__((used)) int _write(int fd, const unsigned char *buf, int size)
{
int i;
for (i = 0; i < size; i++)
{
#if(BLOCK_MODE)
while (read_reg8(USBFIFO) & 0x02);
#endif
write_reg8(EDPS_DAT, buf[i]);
}
return i;
}
#elif ((DEBUG_BUS==DEBUG_IO) && (UART_PRINT_DEBUG_ENABLE))
#ifndef BIT_INTERVAL
#define BIT_INTERVAL (16*1000*1000/PRINT_BAUD_RATE)
#endif
#define UART_DEBUG_TX_PIN_REG ((0x140303 + ((DEBUG_INFO_TX_PIN>>8)<<3)))
/**
* @brief This function serves to foramt string by GPIO simulate uart.
* @param[in] byte - a byte need to print
* @return none.
*/
_attribute_ram_code_sec_noinline_ void dr_putchar(unsigned char byte){
unsigned char j = 0;
unsigned int t1 = 0;
unsigned int t2 = 0;
unsigned int pcTxReg = UART_DEBUG_TX_PIN_REG;
unsigned char tmp_bit0 = read_reg8(pcTxReg) & (~(DEBUG_INFO_TX_PIN & 0xff));
unsigned char tmp_bit1 = read_reg8(pcTxReg) | (DEBUG_INFO_TX_PIN & 0xff);
unsigned char bit[10] = {0};
bit[0] = tmp_bit0;
bit[1] = (byte & 0x01)? tmp_bit1 : tmp_bit0;
bit[2] = ((byte>>1) & 0x01)? tmp_bit1 : tmp_bit0;
bit[3] = ((byte>>2) & 0x01)? tmp_bit1 : tmp_bit0;
bit[4] = ((byte>>3) & 0x01)? tmp_bit1 : tmp_bit0;
bit[5] = ((byte>>4) & 0x01)? tmp_bit1 : tmp_bit0;
bit[6] = ((byte>>5) & 0x01)? tmp_bit1 : tmp_bit0;
bit[7] = ((byte>>6) & 0x01)? tmp_bit1 : tmp_bit0;
bit[8] = ((byte>>7) & 0x01)? tmp_bit1 : tmp_bit0;
bit[9] = tmp_bit1;
t1 = clock_time();//eagle stimer register
for(j = 0;j<10;j++)
{
t2=t1;
while(t1 - t2 < BIT_INTERVAL){
t1 = clock_time();
}
write_reg8(pcTxReg,bit[j]); //send bit0
}
}
__attribute__((used)) int _write(int fd, const unsigned char *buf, int size)
{
int i;
for (i = 0; i < size; i++){
dr_putchar(buf[i]);
}
return i;
}
void array_printf(unsigned char*data, unsigned int len) {
printf("{");
for(int i = 0; i < len; ++i){
printf("%X%s", data[i], i<(len)-1? ":":" ");
}
printf("}\n");
}
#else
//keep safe, if user call printf func, smp will be wrong, if no printf is used, below can be removed.
__attribute__((used)) int _write(int fd, const unsigned char *buf, int size)
{
return 0;
}
#endif
#endif
+51
View File
@@ -0,0 +1,51 @@
/********************************************************************************************************
* @file printf.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include "drivers.h"
#include <stdio.h>
#define DEBUG_MODE 1
#if(DEBUG_MODE==1)
#define DEBUG_IO 0
#define DEBUG_USB 1
#define DEBUG_BUS DEBUG_IO
#if (DEBUG_BUS==DEBUG_USB)
#define EDPS_DAT (0x100818 |0x80000000)
#define USBFIFO (0x10083d |0x80000000)
#define FIFOTHRESHOLD 4
#define BLOCK_MODE 0
#else /* DEBUG_IO */
#if (UART_PRINT_DEBUG_ENABLE)
void array_printf(unsigned char*data, unsigned int len);
#else
#define array_printf
#define printf
#endif
#endif
#endif
+204
View File
@@ -0,0 +1,204 @@
/********************************************************************************************************
* @file rf_frame.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#ifndef _RF_FRAME_H_
#define _RF_FRAME_H_
#include "../drivers.h"
#include "keyboard/keyboard.h"
#define RF_PROTO_BYTE 0x51
#define PIPE0_CODE 0x55556666
#define PIPE1_CODE 0xaabbccdd
#define MOUSE_FRAME_DATA_NUM 4
typedef struct {
u8 btn;
s8 x;
s8 y;
s8 wheel;
}mouse_data_t;
typedef struct{
u32 dma_len; //won't be a fixed number as previous, should adjust with the mouse package number
u8 rf_len;
u8 proto;
u8 flow;
u8 type;
// u32 gid0; //pipe0 code, used as sync code for control pipe in hamster
u8 rssi;
u8 per;
u8 seq_no;
u8 rsvd;
u32 did;
}rf_packet_pairing_t;
typedef struct {
u32 dma_len; //won't be a fixed number as previous, should adjust with the mouse package number
u8 rf_len;
u8 proto;
u8 flow;
u8 type;
// u32 gid; //pipe0 code, used as sync code for control pipe in hamster
u8 rssi;
u8 per;
u8 seq_no;
u8 pno;
u8 data[MOUSE_FRAME_DATA_NUM*sizeof(mouse_data_t)]; //now the data length is variable, if the previous no ACK, data will send again in next time
}rf_packet_mouse_t;
typedef struct {
u32 dma_len; //won't be a fixed number as previous, should adjust with the mouse package number
u8 rf_len;
u8 proto;
u8 flow;
u8 type;
// u32 gid; //pipe0 code, used as sync code for control pipe in hamster
u8 rssi;
u8 per;
u8 seq_no;
u8 pno;
u32 did;
u8 data[4*sizeof(kb_data_t)]; //now the data length is variable, if the previous no ACK, data will send again in next time
}rf_packet_keyboard_t;
////////////////////////// host side ///////////////////////////////
typedef struct{
u32 dma_len;
u8 rf_len;
u8 proto;
u8 flow;
u8 type;
// u32 gid0;
u8 rssi;
u8 per;
u16 tick;
u8 chn;
u8 info0;
u8 info1;
u8 info2;
u32 gid1;
u32 did;
}rf_packet_debug_t;
typedef struct{
u32 dma_len; //won't be a fixed number as previous, should adjust with the mouse package number
u8 rf_len;
u8 proto;
u8 flow;
u8 type;
// u32 gid0; //pipe0 code, used as sync code for control pipe in hamster
u8 rssi;
u8 per;
u16 tick;
u8 chn;
}rf_ack_empty_t;
typedef struct{
u32 dma_len; //won't be a fixed number as previous, should adjust with the mouse package number
u8 rf_len;
u8 proto;
u8 flow;
u8 type;
// u32 gid0; //pipe0 code, used as sync code for control pipe in hamster
u8 rssi;
u8 per;
u16 tick;
u8 chn;
u8 info0;
u8 info1;
u8 info2;
u32 gid1; //pipe1 code, used as sync code for data pipe in hamster
u32 did;
}rf_packet_ack_pairing_t;
typedef struct{
u32 dma_len; //won't be a fixed number as previous, should adjust with the mouse package number
u8 rf_len;
u8 proto;
u8 flow;
u8 type;
// u32 gid; //pipe0 code, used as sync code for control pipe in hamster
u8 rssi;
u8 per;
u16 tick;
u8 chn;
u8 info;
}rf_packet_ack_mouse_t;
typedef struct{
u32 dma_len; //won't be a fixed number as previous, should adjust with the mouse package number
u8 rf_len;
u8 proto;
u8 flow;
u8 type;
// u32 gid; //pipe0 code, used as sync code for control pipe in hamster
u8 rssi;
u8 per;
u16 tick;
u8 chn;
u8 status;
}rf_packet_ack_keyboard_t;
#endif /* LED_RF_FRAME_H_ */
+353
View File
@@ -0,0 +1,353 @@
/********************************************************************************************************
* @file AudioClassCommon.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
/* Includes: */
#include "tl_common.h"
#include "StdDescriptors.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
#define AUDIO_CHANNEL_LEFT_FRONT BIT(0)
#define AUDIO_CHANNEL_RIGHT_FRONT BIT(1)
#define AUDIO_CHANNEL_CENTER_FRONT BIT(2)
#define AUDIO_CHANNEL_LOW_FREQ_ENHANCE BIT(3)
#define AUDIO_CHANNEL_LEFT_SURROUND BIT(4)
#define AUDIO_CHANNEL_RIGHT_SURROUND BIT(5)
#define AUDIO_CHANNEL_LEFT_OF_CENTER BIT(6)
#define AUDIO_CHANNEL_RIGHT_OF_CENTER BIT(7)
#define AUDIO_CHANNEL_SURROUND BIT(8)
#define AUDIO_CHANNEL_SIDE_LEFT BIT(9)
#define AUDIO_CHANNEL_SIDE_RIGHT BIT(10)
#define AUDIO_CHANNEL_TOP BIT(11)
#define AUDIO_FEATURE_MUTE BIT(0)
#define AUDIO_FEATURE_VOLUME BIT(1)
#define AUDIO_FEATURE_BASS BIT(2)
#define AUDIO_FEATURE_MID BIT(3)
#define AUDIO_FEATURE_TREBLE BIT(4)
#define AUDIO_FEATURE_GRAPHIC_EQUALIZER BIT(5)
#define AUDIO_FEATURE_AUTOMATIC_GAIN BIT(6)
#define AUDIO_FEATURE_DELAY BIT(7)
#define AUDIO_FEATURE_BASS_BOOST BIT(8)
#define AUDIO_FEATURE_BASS_LOUDNESS BIT(9)
#define AUDIO_TERMINAL_UNDEFINED (0x100)
#define AUDIO_TERMINAL_STREAMING (0x101)
#define AUDIO_TERMINAL_VENDOR (0x1FF)
#define AUDIO_TERMINAL_IN_UNDEFINED (0x200)
#define AUDIO_TERMINAL_IN_MIC (0x201)
#define AUDIO_TERMINAL_IN_DESKTOP_MIC (0x202)
#define AUDIO_TERMINAL_IN_PERSONAL_MIC (0x203)
#define AUDIO_TERMINAL_IN_OMNIDIR_MIC (0x204)
#define AUDIO_TERMINAL_IN_MIC_ARRAY (0x205)
#define AUDIO_TERMINAL_IN_PROCESSING_MIC (0x206)
#define AUDIO_TERMINAL_IN_OUT_UNDEFINED (0x300)
#define AUDIO_TERMINAL_OUT_SPEAKER (0x301)
#define AUDIO_TERMINAL_OUT_HEADPHONES (0x302)
#define AUDIO_TERMINAL_OUT_HEAD_MOUNTED (0x303)
#define AUDIO_TERMINAL_OUT_DESKTOP (0x304)
#define AUDIO_TERMINAL_OUT_ROOM (0x305)
#define AUDIO_TERMINAL_OUT_COMMUNICATION (0x306)
#define AUDIO_TERMINAL_OUT_LOWFREQ (0x307)
#define AUDIO_SAMPLE_FREQ(freq) { \
.Byte1 = ((u32)freq & 0xFF), \
.Byte2 = (((u32)freq >> 8) & 0xFF), \
.Byte3 = (((u32)freq >> 16) & 0xFF) \
}
#define AUDIO_EP_FULL_PACKETS_ONLY BIT(7)
#define AUDIO_EP_ACCEPTS_SMALL_PACKETS (0<<7)
#define AUDIO_EP_SAMPLE_FREQ_CONTROL BIT(0)
#define AUDIO_EP_PITCH_CONTROL BIT(1)
enum Audio_Descriptor_ClassSubclassProtocol_t
{
AUDIO_CSCP_StreamingProtocol = 0,
AUDIO_CSCP_ControlProtocol = 0,
AUDIO_CSCP_AudioClass = 1,
AUDIO_CSCP_ControlSubclass = 1,
AUDIO_CSCP_AudioStreamingSubclass,
AUDIO_CSCP_MIDIStreamingSubclass,
};
enum Audio_CSInterface_AC_SubTypes_t
{
AUDIO_DSUBTYPE_CSInterface_Header = 1,
AUDIO_DSUBTYPE_CSInterface_InputTerminal,
AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
AUDIO_DSUBTYPE_CSInterface_Mixer,
AUDIO_DSUBTYPE_CSInterface_Selector,
AUDIO_DSUBTYPE_CSInterface_Feature,
AUDIO_DSUBTYPE_CSInterface_Processing,
AUDIO_DSUBTYPE_CSInterface_Extension,
};
enum Audio_CSInterface_AS_SubTypes_t
{
AUDIO_DSUBTYPE_CSInterface_General = 1,
AUDIO_DSUBTYPE_CSInterface_FormatType,
AUDIO_DSUBTYPE_CSInterface_FormatSpecific,
};
enum Audio_CSEndpoint_SubTypes_t
{
AUDIO_DSUBTYPE_CSEndpoint_General = 1,
};
enum Audio_ClassRequests_t
{
AUDIO_REQ_SetCurrent = 1,
AUDIO_REQ_SetMinimum,
AUDIO_REQ_SetMaximum,
AUDIO_REQ_SetResolution,
AUDIO_REQ_SetMemory,
AUDIO_REQ_GetCurrent = 0x81,
AUDIO_REQ_GetMinimum,
AUDIO_REQ_GetMaximum,
AUDIO_REQ_GetResolution,
AUDIO_REQ_GetMemory,
AUDIO_REQ_GetStatus = 0xFF,
};
enum Audio_EndpointControls_t
{
AUDIO_EPCONTROL_SamplingFreq = 1,
AUDIO_EPCONTROL_Pitch,
};
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 Subtype;
u8 TerminalID;
u16 TerminalType;
u8 AssociatedOutputTerminal;
u8 TotalChannels;
u16 ChannelConfig;
u8 ChannelStrIndex;
u8 TerminalStrIndex;
}USB_Audio_Descriptor_InputTerminal_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u8 DescriptorSubtype;
u8 TerminalID;
u16 TerminalType;
u8 AssocTerminal;
u8 NrChannels;
u16 ChannelConfig;
u8 ChannelNames;
u8 Terminal;
}USB_Audio_StdDescriptor_InputTerminal_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 Subtype;
u8 TerminalID;
u16 TerminalType;
u8 AssociatedInputTerminal;
u8 SourceID;
u8 TerminalStrIndex;
}USB_Audio_Descriptor_OutputTerminal_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u8 DescriptorSubtype;
u8 TerminalID;
u16 TerminalType;
u8 AssocTerminal;
u8 SourceID;
u8 Terminal;
}USB_Audio_StdDescriptor_OutputTerminal_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 Subtype;
u8 ACSpecification[2];
u8 TotalLength[2];
u8 InCollection;
u8 InterfaceNumber;
}USB_Audio_Descriptor_Interface_AC_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 Subtype;
u8 ACSpecification[2];
u8 TotalLength[2];
u8 InCollection;
u8 InterfaceNumber_speaker;
u8 InterfaceNumber_mic;
}USB_Audio_Descriptor_Interface_AC_TL_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u8 DescriptorSubtype;
u8 BcdADC[2];
u8 TotalLength[2];
u8 InCollection;
u8 InterfaceNumbers;
}USB_Audio_StdDescriptor_Interface_AC_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 Subtype;
u8 UnitID;
u8 SourceID;
u8 ControlSize;
u8 ChannelControls[3];
u8 FeatureUnitStrIndex;
}USB_Audio_Descriptor_FeatureUnit_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 Subtype;
u8 UnitID;
u8 SourceID;
u8 ControlSize;
u8 ChannelControls[2];
u8 FeatureUnitStrIndex;
}USB_Audio_Descriptor_FeatureUnit_Mic_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u8 DescriptorSubtype;
u8 UnitID;
u8 SourceID;
u8 ControlSize;
u8 MAControls[3];
u8 Feature;
}USB_Audio_StdDescriptor_FeatureUnit_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 Subtype;
u8 TerminalLink;
u8 FrameDelay;
u8 AudioFormat[2];
}USB_Audio_Descriptor_Interface_AS_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u8 DescriptorSubtype;
u8 TerminalLink;
u8 Delay;
u16 FormatTag;
}USB_Audio_StdDescriptor_Interface_AS_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 Subtype;
u8 FormatType;
u8 Channels;
u8 SubFrameSize;
u8 BitResolution;
u8 TotalDiscreteSampleRates;
}USB_Audio_Descriptor_Format_t;
typedef struct
{
u8 Byte1;
u8 Byte2;
u8 Byte3;
}USB_Audio_SampleFreq_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u8 DescriptorSubtype;
u8 FormatType;
u8 NrChannels;
u8 SubFrameSize;
u8 BitResolution;
u8 SampleFrequencyType;
}USB_Audio_StdDescriptor_Format_t;
typedef struct
{
USB_Descriptor_Endpoint_t Endpoint;
u8 Refresh;
u8 SyncEndpointNumber;
}USB_Audio_Descriptor_StreamEndpoint_Std_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u8 EndpointAddress;
u8 MAttributes;
u16 MaxPacketSize;
u8 Interval;
u8 Refresh;
u8 SynchAddress;
}USB_Audio_StdDescriptor_StreamEndpoint_Std_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 Subtype;
u8 Attributes;
u8 LockDelayUnits;
u8 LockDelay[2];
}USB_Audio_Descriptor_StreamEndpoint_Spc_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u8 DescriptorSubtype;
u8 MAttributes;
u8 LockDelayUnits;
u16 LockDelay;
}USB_Audio_StdDescriptor_StreamEndpoint_Spc_t;
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+178
View File
@@ -0,0 +1,178 @@
/********************************************************************************************************
* @file CDCClassCommon.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
/* Includes: */
#include "application/usbstd/stdDescriptors.h"
#include "tl_common.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
#define CDC_CONTROL_LINE_OUT_DTR BIT(0)
#define CDC_CONTROL_LINE_OUT_RTS BIT(1)
#define CDC_CONTROL_LINE_IN_DCD BIT(0)
#define CDC_CONTROL_LINE_IN_DSR BIT(1)
#define CDC_CONTROL_LINE_IN_BREAK BIT(2)
#define CDC_CONTROL_LINE_IN_RING BIT(3)
#define CDC_CONTROL_LINE_IN_FRAMEERROR BIT(4)
#define CDC_CONTROL_LINE_IN_PARITYERROR BIT(5)
#define CDC_CONTROL_LINE_IN_OVERRUNERROR BIT(6)
#define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \
struct \
{ \
USB_Descriptor_Hdr_t Header; \
u8 SubType; \
u8 Data[DataSize]; \
}
enum CDC_Descriptor_ClassSubclass_Protocol_t
{
CDC_CSCP_NoSpecific_Subclass = 0x00,
CDC_CSCP_NoSpecific_Protocol = 0x00,
CDC_CSCP_NoData_Subclass = 0x00,
CDC_CSCP_NoData_Protocol = 0x00,
CDC_CSCP_ATCmd_Protocol = 0x01,
CDC_CSCP_CDC_Class = 0x02,
CDC_CSCP_ACM_Subclass = 0x02,
CDC_CSCP_CDCData_Class = 0x0A,
CDC_CSCP_VendorSpecific_Protocol = 0xFF,
};
enum CDC_Class_Requestions_t
{
CDC_REQ_SendEncapsulated_Cmd,
CDC_REQ_GetEncapsulated_Rsp,
CDC_REQ_SetLine_Encoding = 0x20,
CDC_REQ_GetLine_Encoding,
CDC_REQ_SetControlLine_State,
CDC_REQ_SendBreak,
};
enum CDC_Class_Notifications_t
{
CDC_NOTIF_Serial_State = 0x20,
};
enum CDC_Descriptor_Subtypes_t
{
CDC_DSUBTYPE_CSInterface_Header,
CDC_DSUBTYPE_CSInterface_CallManagement,
CDC_DSUBTYPE_CSInterface_ACM,
CDC_DSUBTYPE_CSInterface_DirectLine,
CDC_DSUBTYPE_CSInterface_TelephoneRinger,
CDC_DSUBTYPE_CSInterface_TelephoneCall,
CDC_DSUBTYPE_CSInterface_Union,
CDC_DSUBTYPE_CSInterface_CountrySelection,
CDC_DSUBTYPE_CSInterface_TelephoneOpModes,
CDC_DSUBTYPE_CSInterface_USBTerminal,
CDC_DSUBTYPE_CSInterface_NetworkChannel,
CDC_DSUBTYPE_CSInterface_ProtocolUnit,
CDC_DSUBTYPE_CSInterface_ExtensionUnit,
CDC_DSUBTYPE_CSInterface_MultiChannel,
CDC_DSUBTYPE_CSInterface_CAPI,
CDC_DSUBTYPE_CSInterface_Ethernet,
CDC_DSUBTYPE_CSInterface_ATM,
};
enum CDC_LineEncoding_Formats_t
{
CDC_LINEENCODING_OneStopBit,
CDC_LINEENCODING_OneAndAHalfStopBits,
CDC_LINEENCODING_TwoStopBits,
};
enum CDC_LineEncoding_Parity_t
{
CDC_PARITY_None,
CDC_PARITY_Odd,
CDC_PARITY_Even,
CDC_PARITY_Mark,
CDC_PARITY_Space,
};
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 Subtype;
u16 CDCSpecification;
} USB_CDC_Descriptor_FunctionalHeader_t;
typedef struct
{
u8 bFunctionLength;
u8 bDescriptorType;
u8 bDescriptorSubType;
u16 bcdCDC;
} USB_CDC_StdDescriptor_FunctionalHeader_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 Subtype;
u8 Capabilities;
} USB_CDC_Descriptor_FunctionalACM_t;
typedef struct
{
u8 bFunctionLength;
u8 bDescriptorType;
u8 bDescriptorSubType;
u8 bmCapabilities;
} USB_CDC_StdDescriptor_FunctionalACM_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 Subtype;
u8 MasterInterfaceNumber;
u8 SlaveInterfaceNumber;
} USB_CDC_Descriptor_FunctionalUnion_t;
typedef struct
{
u8 bFunctionLength;
u8 bDescriptorType;
u8 bDescriptorSubType;
u8 bMasterInterface;
u8 bSlaveInterface0;
} USB_CDC_StdDescriptor_FunctionalUnion_t;
typedef struct
{
u32 BaudRateBPS;
u8 CharFormat;
u8 ParityType;
u8 DataBits;
} CDC_LineEncoding_t;
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+66
View File
@@ -0,0 +1,66 @@
/********************************************************************************************************
* @file CDCClassDevice.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
/* Includes: */
#include <application/usbstd/CDCClassCommon.h>
#include "../common/types.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
typedef struct
{
struct
{
u8 ControlInterfaceNumber;
u8 DataINEndpointNumber;
u16 DataINEndpointSize;
bool DataINEndpointDoubleBank;
u8 DataOUTEndpointNumber;
u16 DataOUTEndpointSize;
bool DataOUTEndpointDoubleBank;
u8 NotificationEndpointNumber;
u16 NotificationEndpointSize;
bool NotificationEndpointDoubleBank;
} Config;
struct
{
struct
{
u16 HostToDevice;
u16 DeviceToHost;
} ControlLineStates;
CDC_LineEncoding_t LineEncoding;
} State;
} USB_ClassInfo_CDC_Device_t;
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+449
View File
@@ -0,0 +1,449 @@
/********************************************************************************************************
* @file HIDClassCommon.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
/* Includes: */
#include "application/usbstd/stdDescriptors.h"
#include "tl_common.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
#define HID_KEYBOARD_MODIFIER_LEFTCTRL BIT(0)
#define HID_KEYBOARD_MODIFIER_LEFTSHIFT BIT(1)
#define HID_KEYBOARD_MODIFIER_LEFTALT BIT(2)
#define HID_KEYBOARD_MODIFIER_LEFTGUI BIT(3)
#define HID_KEYBOARD_MODIFIER_RIGHTCTRL BIT(4)
#define HID_KEYBOARD_MODIFIER_RIGHTSHIFT BIT(5)
#define HID_KEYBOARD_MODIFIER_RIGHTALT BIT(6)
#define HID_KEYBOARD_MODIFIER_RIGHTGUI BIT(7)
#define HID_KEYBOARD_LED_NUMLOCK BIT(0)
#define HID_KEYBOARD_LED_CAPSLOCK BIT(1)
#define HID_KEYBOARD_LED_SCROLLLOCK BIT(2)
#define HID_KEYBOARD_LED_KATANA BIT(3)
#define HID_KEYBOARD_SC_ERROR_ROLLOVER 1
#define HID_KEYBOARD_SC_POST_FAIL 2
#define HID_KEYBOARD_SC_ERROR_UNDEFINED 3
#define HID_KEYBOARD_SC_A 4
#define HID_KEYBOARD_SC_B 5
#define HID_KEYBOARD_SC_C 6
#define HID_KEYBOARD_SC_D 7
#define HID_KEYBOARD_SC_E 8
#define HID_KEYBOARD_SC_F 9
#define HID_KEYBOARD_SC_G 10
#define HID_KEYBOARD_SC_H 11
#define HID_KEYBOARD_SC_I 12
#define HID_KEYBOARD_SC_J 13
#define HID_KEYBOARD_SC_K 14
#define HID_KEYBOARD_SC_L 15
#define HID_KEYBOARD_SC_M 16
#define HID_KEYBOARD_SC_N 17
#define HID_KEYBOARD_SC_O 18
#define HID_KEYBOARD_SC_P 19
#define HID_KEYBOARD_SC_Q 20
#define HID_KEYBOARD_SC_R 21
#define HID_KEYBOARD_SC_S 22
#define HID_KEYBOARD_SC_T 23
#define HID_KEYBOARD_SC_U 24
#define HID_KEYBOARD_SC_V 25
#define HID_KEYBOARD_SC_W 26
#define HID_KEYBOARD_SC_X 27
#define HID_KEYBOARD_SC_Y 28
#define HID_KEYBOARD_SC_Z 29
#define HID_KEYBOARD_SC_1_AND_EXCLAMATION 30
#define HID_KEYBOARD_SC_2_AND_AT 31
#define HID_KEYBOARD_SC_3_AND_HASHMARK 32
#define HID_KEYBOARD_SC_4_AND_DOLLAR 33
#define HID_KEYBOARD_SC_5_AND_PERCENTAGE 34
#define HID_KEYBOARD_SC_6_AND_CARET 35
#define HID_KEYBOARD_SC_7_AND_AND_AMPERSAND 36
#define HID_KEYBOARD_SC_8_AND_ASTERISK 37
#define HID_KEYBOARD_SC_9_AND_OPENING_PARENTHESIS 38
#define HID_KEYBOARD_SC_0_AND_CLOSING_PARENTHESIS 39
#define HID_KEYBOARD_SC_ENTER 40
#define HID_KEYBOARD_SC_ESCAPE 41
#define HID_KEYBOARD_SC_BACKSPACE 42
#define HID_KEYBOARD_SC_TAB 43
#define HID_KEYBOARD_SC_SPACE 44
#define HID_KEYBOARD_SC_MINUS_AND_UNDERSCORE 45
#define HID_KEYBOARD_SC_EQUAL_AND_PLUS 46
#define HID_KEYBOARD_SC_OPENING_BRACKET_AND_OPENING_BRACE 47
#define HID_KEYBOARD_SC_CLOSING_BRACKET_AND_CLOSING_BRACE 48
#define HID_KEYBOARD_SC_BACKSLASH_AND_PIPE 49
#define HID_KEYBOARD_SC_NON_US_HASHMARK_AND_TILDE 50
#define HID_KEYBOARD_SC_SEMICOLON_AND_COLON 51
#define HID_KEYBOARD_SC_APOSTROPHE_AND_QUOTE 52
#define HID_KEYBOARD_SC_GRAVE_ACCENT_AND_TILDE 53
#define HID_KEYBOARD_SC_COMMA_AND_LESS_THAN_SIGN 54
#define HID_KEYBOARD_SC_DOT_AND_GREATER_THAN_SIGN 55
#define HID_KEYBOARD_SC_SLASH_AND_QUESTION_MARK 56
#define HID_KEYBOARD_SC_CAPS_LOCK 57
#define HID_KEYBOARD_SC_F1 58
#define HID_KEYBOARD_SC_F2 59
#define HID_KEYBOARD_SC_F3 60
#define HID_KEYBOARD_SC_F4 61
#define HID_KEYBOARD_SC_F5 62
#define HID_KEYBOARD_SC_F6 63
#define HID_KEYBOARD_SC_F7 64
#define HID_KEYBOARD_SC_F8 65
#define HID_KEYBOARD_SC_F9 66
#define HID_KEYBOARD_SC_F10 67
#define HID_KEYBOARD_SC_F11 68
#define HID_KEYBOARD_SC_F12 69
#define HID_KEYBOARD_SC_PRINT_SCREEN 70
#define HID_KEYBOARD_SC_SCROLL_LOCK 71
#define HID_KEYBOARD_SC_PAUSE 72
#define HID_KEYBOARD_SC_INSERT 73
#define HID_KEYBOARD_SC_HOME 74
#define HID_KEYBOARD_SC_PAGE_UP 75
#define HID_KEYBOARD_SC_DELETE 76
#define HID_KEYBOARD_SC_END 77
#define HID_KEYBOARD_SC_PAGE_DOWN 78
#define HID_KEYBOARD_SC_RIGHT_ARROW 79
#define HID_KEYBOARD_SC_LEFT_ARROW 80
#define HID_KEYBOARD_SC_DOWN_ARROW 81
#define HID_KEYBOARD_SC_UP_ARROW 82
#define HID_KEYBOARD_SC_NUM_LOCK 83
#define HID_KEYBOARD_SC_KEYPAD_SLASH 84
#define HID_KEYBOARD_SC_KEYPAD_ASTERISK 85
#define HID_KEYBOARD_SC_KEYPAD_MINUS 86
#define HID_KEYBOARD_SC_KEYPAD_PLUS 87
#define HID_KEYBOARD_SC_KEYPAD_ENTER 88
#define HID_KEYBOARD_SC_KEYPAD_1_AND_END 89
#define HID_KEYBOARD_SC_KEYPAD_2_AND_DOWN_ARROW 90
#define HID_KEYBOARD_SC_KEYPAD_3_AND_PAGE_DOWN 91
#define HID_KEYBOARD_SC_KEYPAD_4_AND_LEFT_ARROW 92
#define HID_KEYBOARD_SC_KEYPAD_5 93
#define HID_KEYBOARD_SC_KEYPAD_6_AND_RIGHT_ARROW 94
#define HID_KEYBOARD_SC_KEYPAD_7_AND_HOME 95
#define HID_KEYBOARD_SC_KEYPAD_8_AND_UP_ARROW 96
#define HID_KEYBOARD_SC_KEYPAD_9_AND_PAGE_UP 97
#define HID_KEYBOARD_SC_KEYPAD_0_AND_INSERT 98
#define HID_KEYBOARD_SC_KEYPAD_DOT_AND_DELETE 99
#define HID_KEYBOARD_SC_NON_US_BACKSLASH_AND_PIPE 100
#define HID_KEYBOARD_SC_POWER 102
#define HID_KEYBOARD_SC_EQUAL_SIGN 103
#define HID_KEYBOARD_SC_F13 104
#define HID_KEYBOARD_SC_F14 105
#define HID_KEYBOARD_SC_F15 106
#define HID_KEYBOARD_SC_F16 107
#define HID_KEYBOARD_SC_F17 108
#define HID_KEYBOARD_SC_F18 109
#define HID_KEYBOARD_SC_F19 110
#define HID_KEYBOARD_SC_F20 111
#define HID_KEYBOARD_SC_F21 112
#define HID_KEYBOARD_SC_F22 113
#define HID_KEYBOARD_SC_F23 114
#define HID_KEYBOARD_SC_F24 115
#define HID_KEYBOARD_SC_EXECUTE 116
#define HID_KEYBOARD_SC_HELP 117
#define HID_KEYBOARD_SC_MANU 118
#define HID_KEYBOARD_SC_SELECT 119
#define HID_KEYBOARD_SC_STOP 120
#define HID_KEYBOARD_SC_AGAIN 121
#define HID_KEYBOARD_SC_UNDO 122
#define HID_KEYBOARD_SC_CUT 123
#define HID_KEYBOARD_SC_COPY 124
#define HID_KEYBOARD_SC_PASTE 125
#define HID_KEYBOARD_SC_FIND 126
#define HID_KEYBOARD_SC_MUTE 127
#define HID_KEYBOARD_SC_VOLUME_UP 128
#define HID_KEYBOARD_SC_VOLUME_DOWN 129
#define HID_KEYBOARD_SC_LOCKING_CAPS_LOCK 130
#define HID_KEYBOARD_SC_LOCKING_NUM_LOCK 131
#define HID_KEYBOARD_SC_LOCKING_SCROLL_LOCK 132
#define HID_KEYBOARD_SC_KEYPAD_COMMA 133
#define HID_KEYBOARD_SC_KEYPAD_EQUAL_SIGN 134
#define HID_KEYBOARD_SC_INTERNATIONAL1 135
#define HID_KEYBOARD_SC_INTERNATIONAL2 136
#define HID_KEYBOARD_SC_INTERNATIONAL3 137
#define HID_KEYBOARD_SC_INTERNATIONAL4 138
#define HID_KEYBOARD_SC_INTERNATIONAL5 139
#define HID_KEYBOARD_SC_INTERNATIONAL6 140
#define HID_KEYBOARD_SC_INTERNATIONAL7 141
#define HID_KEYBOARD_SC_INTERNATIONAL8 142
#define HID_KEYBOARD_SC_INTERNATIONAL9 143
#define HID_KEYBOARD_SC_LANG1 144
#define HID_KEYBOARD_SC_LANG2 145
#define HID_KEYBOARD_SC_LANG3 146
#define HID_KEYBOARD_SC_LANG4 147
#define HID_KEYBOARD_SC_LANG5 148
#define HID_KEYBOARD_SC_LANG6 149
#define HID_KEYBOARD_SC_LANG7 150
#define HID_KEYBOARD_SC_LANG8 151
#define HID_KEYBOARD_SC_LANG9 152
#define HID_KEYBOARD_SC_ALTERNATE_ERASE 153
#define HID_KEYBOARD_SC_SISREQ 154
#define HID_KEYBOARD_SC_CANCEL 155
#define HID_KEYBOARD_SC_CLEAR 156
#define HID_KEYBOARD_SC_PRIOR 157
#define HID_KEYBOARD_SC_RETURN 158
#define HID_KEYBOARD_SC_SEPARATOR 159
#define HID_KEYBOARD_SC_OUT 160
#define HID_KEYBOARD_SC_OPER 161
#define HID_KEYBOARD_SC_CLEAR_AND_AGAIN 162
#define HID_KEYBOARD_SC_CRSEL_ANDPROPS 163
#define HID_KEYBOARD_SC_EXSEL 164
#define HID_KEYBOARD_SC_KEYPAD_00 176
#define HID_KEYBOARD_SC_KEYPAD_000 177
#define HID_KEYBOARD_SC_THOUSANDS_SEPARATOR 178
#define HID_KEYBOARD_SC_DECIMAL_SEPARATOR 179
#define HID_KEYBOARD_SC_CURRENCY_UNIT 180
#define HID_KEYBOARD_SC_CURRENCY_SUB_UNIT 181
#define HID_KEYBOARD_SC_KEYPAD_OPENING_PARENTHESIS 182
#define HID_KEYBOARD_SC_KEYPAD_CLOSING_PARENTHESIS 183
#define HID_KEYBOARD_SC_KEYPAD_OPENING_BRACE 184
#define HID_KEYBOARD_SC_KEYPAD_CLOSING_BRACE 185
#define HID_KEYBOARD_SC_KEYPAD_TAB 186
#define HID_KEYBOARD_SC_KEYPAD_BACKSPACE 187
#define HID_KEYBOARD_SC_KEYPAD_A 188
#define HID_KEYBOARD_SC_KEYPAD_B 189
#define HID_KEYBOARD_SC_KEYPAD_C 190
#define HID_KEYBOARD_SC_KEYPAD_D 191
#define HID_KEYBOARD_SC_KEYPAD_E 192
#define HID_KEYBOARD_SC_KEYPAD_F 193
#define HID_KEYBOARD_SC_KEYPAD_XOR 194
#define HID_KEYBOARD_SC_KEYPAD_CARET 195
#define HID_KEYBOARD_SC_KEYPAD_PERCENTAGE 196
#define HID_KEYBOARD_SC_KEYPAD_LESS_THAN_SIGN 197
#define HID_KEYBOARD_SC_KEYPAD_GREATER_THAN_SIGN 198
#define HID_KEYBOARD_SC_KEYPAD_AMP 199
#define HID_KEYBOARD_SC_KEYPAD_AMP_AMP 200
#define HID_KEYBOARD_SC_KEYPAD_PIPE 201
#define HID_KEYBOARD_SC_KEYPAD_PIPE_PIPE 202
#define HID_KEYBOARD_SC_KEYPAD_COLON 203
#define HID_KEYBOARD_SC_KEYPAD_HASHMARK 204
#define HID_KEYBOARD_SC_KEYPAD_SPACE 205
#define HID_KEYBOARD_SC_KEYPAD_AT 206
#define HID_KEYBOARD_SC_KEYPAD_EXCLAMATION_SIGN 207
#define HID_KEYBOARD_SC_KEYPAD_MEMORY_STORE 208
#define HID_KEYBOARD_SC_KEYPAD_MEMORY_RECALL 209
#define HID_KEYBOARD_SC_KEYPAD_MEMORY_CLEAR 210
#define HID_KEYBOARD_SC_KEYPAD_MEMORY_ADD 211
#define HID_KEYBOARD_SC_KEYPAD_MEMORY_SUBTRACT 212
#define HID_KEYBOARD_SC_KEYPAD_MEMORY_MULTIPLY 213
#define HID_KEYBOARD_SC_KEYPAD_MEMORY_DIVIDE 214
#define HID_KEYBOARD_SC_KEYPAD_PLUS_AND_MINUS 215
#define HID_KEYBOARD_SC_KEYPAD_CLEAR 216
#define HID_KEYBOARD_SC_KEYPAD_CLEAR_ENTRY 217
#define HID_KEYBOARD_SC_KEYPAD_BINARY 218
#define HID_KEYBOARD_SC_KEYPAD_OCTAL 219
#define HID_KEYBOARD_SC_KEYPAD_DECIMAL 220
#define HID_KEYBOARD_SC_KEYPAD_HEXADECIMAL 221
#define HID_KEYBOARD_SC_LEFT_CONTROL 224
#define HID_KEYBOARD_SC_LEFT_SHIFT 225
#define HID_KEYBOARD_SC_LEFT_ALT 226
#define HID_KEYBOARD_SC_LEFT_GUI 227
#define HID_KEYBOARD_SC_RIGHT_CONTROL 228
#define HID_KEYBOARD_SC_RIGHT_SHIFT 229
#define HID_KEYBOARD_SC_RIGHT_ALT 230
#define HID_KEYBOARD_SC_RIGHT_GUI 231
#define HID_DESCRIPTOR_JOYSTICK(NumAxis, MinAxisVal, MaxAxisVal, MinPhysicalVal, MaxPhysicalVal, Buttons) \
HID_RPT_USAGE_PAGE (8, 0x01), \
HID_RPT_USAGE (8, 0x04), \
HID_RPT_COLLECTION (8, 0x01), \
HID_RPT_USAGE (8, 0x01), \
HID_RPT_COLLECTION (8, 0x00), \
HID_RPT_USAGE_MINIMUM (8, 0x30), \
HID_RPT_USAGE_MAXIMUM (8, (0x30 + (NumAxis - 1))), \
HID_RPT_LOGICAL_MINIMUM (16, MinAxisVal), \
HID_RPT_LOGICAL_MAXIMUM (16, MaxAxisVal), \
HID_RPT_PHYSICAL_MINIMUM(16, MinPhysicalVal), \
HID_RPT_PHYSICAL_MAXIMUM(16, MaxPhysicalVal), \
HID_RPT_REPORT_COUNT (8, NumAxis), \
HID_RPT_REPORT_SIZE (8, ((((MinAxisVal >= -0xFF) && (MaxAxisVal <= 0xFF)) ? 8 : 16))), \
HID_RPT_INPUT (8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
HID_RPT_END_COLLECTION (0), \
HID_RPT_USAGE_PAGE (8, 0x09), \
HID_RPT_USAGE_MINIMUM (8, 0x01), \
HID_RPT_USAGE_MAXIMUM (8, Buttons), \
HID_RPT_LOGICAL_MINIMUM (8, 0x00), \
HID_RPT_LOGICAL_MAXIMUM (8, 0x01), \
HID_RPT_REPORT_SIZE (8, 0x01), \
HID_RPT_REPORT_COUNT (8, Buttons), \
HID_RPT_INPUT (8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
HID_RPT_REPORT_SIZE (8, (8 - (Buttons % 8))), \
HID_RPT_REPORT_COUNT (8, 0x01), \
HID_RPT_INPUT (8, HID_IOF_CONSTANT), \
HID_RPT_END_COLLECTION (0)
#define HID_DESCRIPTOR_KEYBOARD(MaxKeys) \
HID_RPT_USAGE_PAGE (8, 0x01), \
HID_RPT_USAGE (8, 0x06), \
HID_RPT_COLLECTION (8, 0x01), \
HID_RPT_USAGE_PAGE (8, 0x07), \
HID_RPT_USAGE_MINIMUM (8, 0xE0), \
HID_RPT_USAGE_MAXIMUM (8, 0xE7), \
HID_RPT_LOGICAL_MINIMUM (8, 0x00), \
HID_RPT_LOGICAL_MAXIMUM (8, 0x01), \
HID_RPT_REPORT_COUNT (8, 0x08), \
HID_RPT_REPORT_SIZE (8, 0x01), \
HID_RPT_INPUT (8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
HID_RPT_INPUT (8, HID_IOF_CONSTANT | HID_IOF_VARIABLE), \
HID_RPT_REPORT_COUNT (8, 0x05), \
HID_RPT_USAGE_PAGE (8, 0x08), \
HID_RPT_USAGE_MINIMUM (8, 0x01), \
HID_RPT_USAGE_MAXIMUM (8, 0x05), \
HID_RPT_OUTPUT (8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), \
HID_RPT_REPORT_COUNT (8, 0x01), \
HID_RPT_REPORT_SIZE (8, 0x03), \
HID_RPT_OUTPUT (8, HID_IOF_CONSTANT), \
HID_RPT_REPORT_COUNT (8, 0x06), \
HID_RPT_REPORT_SIZE (8, 0x08), \
HID_RPT_LOGICAL_MINIMUM (8, 0x00), \
0x26, 0xa4, 0x00, \
HID_RPT_USAGE_PAGE (8, 0x07), \
HID_RPT_USAGE_MINIMUM (8, 0x00), \
0x2a, 0xa4, 0x00, \
HID_RPT_INPUT (8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), \
HID_RPT_END_COLLECTION(0)
#define HID_DESCRIPTOR_MOUSE(MinAxisVal, MaxAxisVal, MinPhysicalVal, MaxPhysicalVal, Buttons, AbsoluteCoords) \
HID_RPT_USAGE_PAGE (8, 0x01), \
HID_RPT_USAGE (8, 0x02), \
HID_RPT_COLLECTION (8, 0x01), \
HID_RPT_USAGE (8, 0x01), \
HID_RPT_COLLECTION (8, 0x00), \
HID_RPT_USAGE_PAGE (8, 0x09), \
HID_RPT_USAGE_MINIMUM (8, 0x01), \
HID_RPT_USAGE_MAXIMUM (8, Buttons), \
HID_RPT_LOGICAL_MINIMUM (8, 0x00), \
HID_RPT_LOGICAL_MAXIMUM (8, 0x01), \
HID_RPT_REPORT_COUNT (8, Buttons), \
HID_RPT_REPORT_SIZE (8, 0x01), \
HID_RPT_INPUT (8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
HID_RPT_REPORT_COUNT (8, 0x01), \
HID_RPT_REPORT_SIZE (8, (8 - (Buttons % 8))), \
HID_RPT_INPUT (8, HID_IOF_CONSTANT), \
HID_RPT_USAGE_PAGE (8, 0x01), \
HID_RPT_USAGE (8, 0x30), \
HID_RPT_USAGE (8, 0x31), \
HID_RPT_LOGICAL_MINIMUM (16, MinAxisVal), \
HID_RPT_LOGICAL_MAXIMUM (16, MaxAxisVal), \
HID_RPT_PHYSICAL_MINIMUM (16, MinPhysicalVal), \
HID_RPT_PHYSICAL_MAXIMUM (16, MaxPhysicalVal), \
HID_RPT_REPORT_COUNT (8, 0x02), \
HID_RPT_REPORT_SIZE (8, ((((MinAxisVal >= -0xFF) && (MaxAxisVal <= 0xFF)) ? 8 : 16))), \
HID_RPT_INPUT (8, HID_IOF_DATA | HID_IOF_VARIABLE | (AbsoluteCoords ? HID_IOF_ABSOLUTE : HID_IOF_RELATIVE)), \
HID_RPT_END_COLLECTION (0), \
HID_RPT_END_COLLECTION(0)
#define HID_DESCRIPTOR_VENDOR(VendorPageNum, CollectionUsage, DataINUsage, DataOUTUsage, NumBytes) \
HID_RPT_USAGE_PAGE (16, (0xFF00 | VendorPageNum)), \
HID_RPT_USAGE (8, CollectionUsage), \
HID_RPT_COLLECTION (8, 0x01), \
HID_RPT_USAGE (8, DataINUsage), \
HID_RPT_LOGICAL_MINIMUM (8, 0x00), \
HID_RPT_LOGICAL_MAXIMUM (8, 0xFF), \
HID_RPT_REPORT_SIZE (8, 0x08), \
HID_RPT_REPORT_COUNT (8, NumBytes), \
HID_RPT_INPUT (8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
HID_RPT_USAGE (8, DataOUTUsage), \
HID_RPT_LOGICAL_MINIMUM (8, 0x00), \
HID_RPT_LOGICAL_MAXIMUM (8, 0xFF), \
HID_RPT_REPORT_SIZE (8, 0x08), \
HID_RPT_REPORT_COUNT (8, NumBytes), \
HID_RPT_OUTPUT (8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), \
HID_RPT_END_COLLECTION (0)
enum HID_Descriptor_ClassSubclassProtocol_t
{
HID_CSCP_NonBootSubclass = 0x00,
HID_CSCP_NonBootProtocol = 0x00,
HID_CSCP_BootSubclass = 0x01,
HID_CSCP_KeyboardBootProtocol = 0x01,
HID_CSCP_MouseBootProtocol,
HID_CSCP_HIDClass,
};
enum HID_ClassRequests_t
{
HID_REQ_GetReport = 0x01,
HID_REQ_GetIdle,
HID_REQ_GetProtocol,
HID_REQ_SetReport = 0x09,
HID_REQ_SetIdle,
HID_REQ_SetProtocol,
};
enum HID_DescriptorTypes_t
{
HID_DTYPE_HID = 0x21,
HID_DTYPE_Report,
};
enum HID_ReportItemTypes_t
{
HID_REPORT_ITEM_In,
HID_REPORT_ITEM_Out,
HID_REPORT_ITEM_Feature,
HID_REPORT_CUSTOM,
};
typedef struct
{
USB_Descriptor_Hdr_t Header;
u16 HIDSpec;
u8 CountryCode;
u8 TotalReportDescriptors;
u8 HIDReportType;
u8 HIDReportLength[2];
}USB_HID_Descriptor_HID_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u16 BcdHID;
u8 CountryCode;
u8 NumDescriptors;
u8 DescriptorType2;
u8 DescriptorLength[2];
}USB_HID_StdDescriptor_HID_t;
typedef struct
{
u8 Button;
s8 X;
s8 Y;
}USB_MouseReport_Data_t;
typedef struct
{
u8 Modifier;
u8 Reserved;
u8 KeyCode[6];
}USB_KeyboardReport_Data_t;
typedef u8 USB_Descriptor_HIDReport_Datatype_t;
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+58
View File
@@ -0,0 +1,58 @@
/********************************************************************************************************
* @file HIDClassDevice.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
/* Includes: */
#include "../common/types.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
typedef struct
{
u8 InterfaceNumber;
u8 ReportINEndpointNumber;
u16 ReportINEndpointSize;
bool ReportINEndpointDoubleBank;
void* PrevReportINBuffer;
u8 PrevReportINBufferSize;
} usbhid_config_t;
typedef struct
{
bool UsingReportProtocol;
u16 PrevFrameNum;
u16 IdleCount;
u16 IdleMSRemaining;
} usbhid_state_t;
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+110
View File
@@ -0,0 +1,110 @@
/********************************************************************************************************
* @file HIDReportData.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#define HID_RPT_DATA_SIZE_MASK (0x03)
#define HID_RPT_TYPE_MASK (0x0C)
#define HID_RPT_TAG_MASK (0xF0)
#define HID_RPT_TYPE_MAIN (0x00)
#define HID_RPT_TYPE_GLOBAL (0x04)
#define HID_RPT_TYPE_LOCAL (0x08)
#define HID_RPT_DATA_BITS_0 (0x00)
#define HID_RPT_DATA_BITS_8 (0x01)
#define HID_RPT_DATA_BITS_16 (0x02)
#define HID_RPT_DATA_BITS_32 (0x03)
#define HID_RPT_DATA_BITS(Data_bits) HID_RPT_DATA_BITS_##Data_bits
#define _HID_RPT_DATA_ENCODE_0(Data)
#define _HID_RPT_DATA_ENCODE_8(Data) , (Data & 0xFF)
#define _HID_RPT_DATA_ENCODE_16(Data) _HID_RPT_DATA_ENCODE_8(Data) _HID_RPT_DATA_ENCODE_8(Data>>8)
#define _HID_RPT_DATA_ENCODE_32(Data) _HID_RPT_DATA_ENCODE_16(Data) _HID_RPT_DATA_ENCODE_16(Data>>16)
#define _HID_RPT_DATA_ENCODE(Data_bits, ...) _HID_RPT_DATA_ENCODE_##Data_bits(__VA_ARGS__)
#define _HID_RPT_DATA_ENTRY(Type, Tag, Data_bits, ...) \
(Type | Tag | HID_RPT_DATA_BITS(Data_bits)) _HID_RPT_DATA_ENCODE(Data_bits, (__VA_ARGS__))
#define HID_IOF_CONSTANT BIT(0)
#define HID_IOF_DATA (0<<0)
#define HID_IOF_VARIABLE BIT(1)
#define HID_IOF_ARRAY (0<<1)
#define HID_IOF_RELATIVE BIT(2)
#define HID_IOF_ABSOLUTE (0<<2)
#define HID_IOF_WRAP BIT(3)
#define HID_IOF_NO_WRAP (0<<3)
#define HID_IOF_NON_LINEAR BIT(4)
#define HID_IOF_LINEAR (0<<4)
#define HID_IOF_NO_PREFERRED_STATE BIT(5)
#define HID_IOF_PREFERRED_STATE (0<<5)
#define HID_IOF_NULLSTATE BIT(6)
#define HID_IOF_NO_NULL_POSITION (0<<6)
#define HID_IOF_VOLATILE BIT(7)
#define HID_IOF_NON_VOLATILE (0<<7)
#define HID_IOF_BUFFERED_BYTES BIT(8)
#define HID_IOF_BITFIELD (0<<8)
#define HID_RPT_INPUT(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_MAIN , \
0x80, Data_bits, __VA_ARGS__)
#define HID_RPT_OUTPUT(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_MAIN , \
0x90, Data_bits, __VA_ARGS__)
#define HID_RPT_COLLECTION(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_MAIN , \
0xA0, Data_bits, __VA_ARGS__)
#define HID_RPT_FEATURE(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_MAIN , \
0xB0, Data_bits, __VA_ARGS__)
#define HID_RPT_END_COLLECTION(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_MAIN , \
0xC0, Data_bits, __VA_ARGS__)
#define HID_RPT_USAGE_PAGE(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_GLOBAL, \
0x00, Data_bits, __VA_ARGS__)
#define HID_RPT_LOGICAL_MINIMUM(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_GLOBAL, \
0x10, Data_bits, __VA_ARGS__)
#define HID_RPT_LOGICAL_MAXIMUM(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_GLOBAL, \
0x20, Data_bits, __VA_ARGS__)
#define HID_RPT_PHYSICAL_MINIMUM(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_GLOBAL, \
0x30, Data_bits, __VA_ARGS__)
#define HID_RPT_PHYSICAL_MAXIMUM(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_GLOBAL, \
0x40, Data_bits, __VA_ARGS__)
#define HID_RPT_UNIT_EXPONENT(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_GLOBAL, \
0x50, Data_bits, __VA_ARGS__)
#define HID_RPT_UNIT(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_GLOBAL, \
0x60, Data_bits, __VA_ARGS__)
#define HID_RPT_REPORT_SIZE(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_GLOBAL, \
0x70, Data_bits, __VA_ARGS__)
#define HID_RPT_REPORT_ID(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_GLOBAL, \
0x80, Data_bits, __VA_ARGS__)
#define HID_RPT_REPORT_COUNT(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_GLOBAL, \
0x90, Data_bits, __VA_ARGS__)
#define HID_RPT_PUSH(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_GLOBAL, \
0xA0, Data_bits, __VA_ARGS__)
#define HID_RPT_POP(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_GLOBAL, \
0xB0, Data_bits, __VA_ARGS__)
#define HID_RPT_USAGE(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_LOCAL , \
0x00, Data_bits, __VA_ARGS__)
#define HID_RPT_USAGE_MINIMUM(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_LOCAL , \
0x10, Data_bits, __VA_ARGS__)
#define HID_RPT_USAGE_MAXIMUM(Data_bits, ...) _HID_RPT_DATA_ENTRY(HID_RPT_TYPE_LOCAL , \
0x20, Data_bits, __VA_ARGS__)
@@ -0,0 +1,178 @@
/********************************************************************************************************
* @file MassStorageClassCommon.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
/* Includes: */
#include <application/usbstd/stdDescriptors.h>
#include "../common/types.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
#pragma pack(1)
#define MS_CBW_SIGNATURE 0x43425355UL
#define MS_CSW_SIGNATURE 0x53425355UL
#define MS_COMMAND_DIR_DATA_OUT (0<<7)
#define MS_COMMAND_DIR_DATA_IN (1<<7)
#define MS_SCSI_CMD_INQUIRY 0x12
#define MS_SCSI_CMD_REQUEST_SENSE 0x03
#define MS_SCSI_CMD_TEST_UNIT_READY 0x00
#define MS_SCSI_CMD_READ_CAPACITY_10 0x25
#define MS_SCSI_CMD_SEND_DIAGNOSTIC 0x1D
#define MS_SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
#define MS_SCSI_CMD_WRITE_10 0x2A
#define MS_SCSI_CMD_READ_10 0x28
#define MS_SCSI_CMD_WRITE_6 0x0A
#define MS_SCSI_CMD_READ_6 0x08
#define MS_SCSI_CMD_VERIFY_10 0x2F
#define MS_SCSI_CMD_MODE_SENSE_6 0x1A
#define MS_SCSI_CMD_MODE_SENSE_10 0x5A
#define MS_SCSI_SENSE_KEY_GOOD 0x00
#define MS_SCSI_SENSE_KEY_RECOVERED_ERROR 0x01
#define MS_SCSI_SENSE_KEY_NOT_READY 0x02
#define MS_SCSI_SENSE_KEY_MEDIUM_ERROR 0x03
#define MS_SCSI_SENSE_KEY_HARDWARE_ERROR 0x04
#define MS_SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05
#define MS_SCSI_SENSE_KEY_UNIT_ATTENTION 0x06
#define MS_SCSI_SENSE_KEY_DATA_PROTECT 0x07
#define MS_SCSI_SENSE_KEY_BLANK_CHECK 0x08
#define MS_SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09
#define MS_SCSI_SENSE_KEY_COPY_ABORTED 0x0A
#define MS_SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B
#define MS_SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D
#define MS_SCSI_SENSE_KEY_MISCOMPARE 0x0E
#define MS_SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00
#define MS_SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04
#define MS_SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24
#define MS_SCSI_ASENSE_NOT_READY_TO_READY_CHANGE 0x28
#define MS_SCSI_ASENSE_WRITE_PROTECTED 0x27
#define MS_SCSI_ASENSE_FORMAT_ERROR 0x31
#define MS_SCSI_ASENSE_INVALID_COMMAND 0x20
#define MS_SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21
#define MS_SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A
#define MS_SCSI_ASENSEQ_NO_QUALIFIER 0x00
#define MS_SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01
#define MS_SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED 0x02
#define MS_SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07
enum MS_Descriptor_ClassSubclassProtocol_t
{
MS_CSCP_MassStorageClass = 0x08,
MS_CSCP_SCSITransparentSubclass = 0x06,
MS_CSCP_BulkOnlyTransportProtocol = 0x50,
};
enum MS_ClassRequests_t
{
MS_REQ_GetMaxLUN = 0xFE,
MS_REQ_MassStorageReset,
};
enum MS_CommandStatusCodes_t
{
MS_MS_SCSI_COMMAND_Pass,
MS_MS_SCSI_COMMAND_Fail,
MS_MS_SCSI_COMMAND_PhaseError,
};
typedef struct
{
u32 Signature;
u32 Tag;
u32 DataTransferLength;
u8 Flags;
u8 LUN;
u8 SCSICommandLength;
u8 SCSICommandData[16];
} MS_CommandBlockWrapper_t;
typedef struct
{
u32 Signature;
u32 Tag;
u32 DataTransferResidue;
u8 Status;
} MS_CommandStatusWrapper_t;
typedef struct
{
u8 ResponseCode;
u8 SegmentNumber;
u8 SenseKey : 4;
u8 Reserved : 1;
u8 ILI : 1;
u8 EOM : 1;
u8 FileMark : 1;
u8 Information[4];
u8 AdditionalLength;
u8 CmdSpecificInformation[4];
u8 AdditionalSenseCode;
u8 AdditionalSenseQualifier;
u8 FieldReplaceableUnitCode;
u8 SenseKeySpecific[3];
} MS_SCSI_Request_Sense_Response_t;
typedef struct
{
u8 DeviceType : 5;
u8 PeripheralQualifier : 3;
u8 Reserved : 7;
u8 Removable : 1;
u8 Version;
u8 ResponseDataFormat : 4;
u8 Reserved2 : 1;
u8 NormACA : 1;
u8 TrmTsk : 1;
u8 AERC : 1;
u8 AdditionalLength;
u8 Reserved3[2];
u8 SoftReset : 1;
u8 CmdQue : 1;
u8 Reserved4 : 1;
u8 Linked : 1;
u8 Sync : 1;
u8 WideBus16Bit : 1;
u8 WideBus32Bit : 1;
u8 RelAddr : 1;
u8 VendorID[8];
u8 ProductID[16];
u8 RevisionID[4];
} MS_SCSI_Inquiry_Response_t;
#pragma pack()
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+55
View File
@@ -0,0 +1,55 @@
/********************************************************************************************************
* @file PrinterClassCommon.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
/* Includes: */
#include "tl_common.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
#define PRNT_PORTSTATUS_NOTERROR BIT(3)
#define PRNT_PORTSTATUS_SELECT BIT(4)
#define PRNT_PORTSTATUS_PAPEREMPTY BIT(5)
enum PRNT_Descriptor_ClassSubclassProtocol_t
{
PRNT_CSCP_PrinterClass = 0x07,
PRNT_CSCP_PrinterSubclass = 0x01,
PRNT_CSCP_BidirectionalProtocol = 0x02,
};
enum PRNT_ClassRequests_t
{
PRNT_REQ_GetDeviceID,
PRNT_REQ_GetPortStatus,
PRNT_REQ_SoftReset,
};
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+85
View File
@@ -0,0 +1,85 @@
/********************************************************************************************************
* @file StdRequestType.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
/* Includes: */
#include "tl_common.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
#define CONTROL_REQTYPE_TYPE 0x60
#define CONTROL_REQTYPE_DIRECTION 0x80
#define CONTROL_REQTYPE_RECIPIENT 0x1F
#define REQDIR_HOSTTODEVICE (0<<7)
#define REQDIR_DEVICETOHOST (1<<7)
#define REQTYPE_STANDARD (0<<5)
#define REQTYPE_CLASS (1<<5)
#define REQTYPE_VENDOR (2<<5)
#define REQREC_DEVICE (0<<0)
#define REQREC_INTERFACE (1<<0)
#define REQREC_ENDPOINT (2<<0)
#define REQREC_OTHER (3<<0)
#define FEATURE_SELFPOWERED_ENABLED (1<<0)
#define FEATURE_REMOTE_WAKEUP_ENABLED (1<<1)
typedef struct
{
u8 RequestType;
u8 Request;
u16 Value;
u16 Index;
u16 Length;
}USB_Request_Hdr_t;
enum USB_Control_Request_t
{
REQ_GetStatus,
REQ_ClearFeature,
REQ_SetFeature = 3,
REQ_SetAddress = 5,
REQ_GetDescriptor,
REQ_SetDescriptor,
REQ_GetConfiguration,
REQ_SetConfiguration,
REQ_GetInterface,
REQ_SetInterface,
REQ_SynchFrame,
};
enum USB_Feature_Selectors_t
{
FEATURE_SEL_EndpointHalt,
FEATURE_SEL_DeviceRemoteWakeup,
FEATURE_SEL_TestMode,
};
#if defined(__cplusplus)
}
#endif
+67
View File
@@ -0,0 +1,67 @@
/********************************************************************************************************
* @file USBController.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/**If Isochronous endpoint,
Bits 3..2 = Synchronisation Type (Iso Mode)
00 = No Synchonisation
01 = Asynchronous
10 = Adaptive
11 = Synchronous
Bits 5..4 = Usage Type (Iso Mode)
00 = Data Endpoint
01 = Feedback Endpoint
10 = Explicit Feedback Data Endpoint
11 = Reserved
*/
#define EP_SYNC_TYPE_NO_SYNC 0
#define EP_SYNC_TYPE_ASYN 1
#define EP_SYNC_TYPE_ADAPTIVE 2
#define EP_SYNC_TYPE_SYNC 3
#define EP_USAGE_TYPE_DATA 0
#define EP_USAGE_TYPE_FEEDBACK 1
#define EP_USAGE_TYPE_FEEDBACK_DATA 2
#define EP_USAGE_TYPE_RSV 3
#define ENDPOINT_DIR_MASK BIT(7)
#define ENDPOINT_DIR_OUT 0
#define ENDPOINT_DIR_IN BIT(7)
#define EP_TYPE_MASK 3
#define EP_TYPE_CONTROL 0
#define EP_TYPE_ISOCHRONOUS 1
#define EP_TYPE_BULK 2
#define EP_TYPE_INTERRUPT 3
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+272
View File
@@ -0,0 +1,272 @@
/********************************************************************************************************
* @file stdDescriptors.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
/* Includes: */
#include "tl_common.h"
#include "drivers.h"
//#include "../mcu/compiler.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
#define NO_DESCRIPTOR (0)
#define USB_CONFIG_POWER_MA(mA) ((mA) >> 1)
#define USB_STRING_LEN(UnicodeChars) (sizeof(USB_Descriptor_Hdr_t) + ((UnicodeChars) << 1))
#define LANGUAGE_ID_ENG (0x0409)
#define USB_CONFIG_ATTR_REMOTEWAKEUP (0x20)
#define USB_CONFIG_ATTR_SELFPOWERED (0x40)
#define USB_CONFIG_ATTR_RESERVED (0x80)
#define ENDPOINT_ATTR_NO_SYNC (0<<2)
#define ENDPOINT_ATTR_ASYNC (1<<2)
#define ENDPOINT_ATTR_ADAPTIVE (2<<2)
#define ENDPOINT_ATTR_SYNC (3<<2)
#define ENDPOINT_USAGE_DATA (0<<4)
#define ENDPOINT_USAGE_FEEDBACK (1<<4)
#define ENDPOINT_USAGE_IMPLICIT_FEEDBACK (2<<4)
enum USB_DescriptorTypes_t
{
DTYPE_Device = 0x01,
DTYPE_Configuration,
DTYPE_String,
DTYPE_Interface,
DTYPE_Endpoint,
DTYPE_DeviceQualifier,
DTYPE_Other,
DTYPE_InterfacePower,
DTYPE_InterfaceAssociation = 0x0B,
DTYPE_CSInterface = 0x24,
DTYPE_CSEndpoint = 0x25,
};
enum USB_Descriptor_ClassSubclassProtocol_t
{
USB_CSCP_NoDeviceClass = 0x00,
USB_CSCP_NoDeviceSubclass = 0x00,
USB_CSCP_NoDeviceProtocol = 0x00,
USB_CSCP_IADDeviceProtocol = 0x01,
USB_CSCP_IADDeviceSubclass = 0x02,
USB_CSCP_IADDeviceClass = 0xEF,
USB_CSCP_VendorSpecificClass = 0xFF,
USB_CSCP_VendorSpecificSubclass = 0xFF,
USB_CSCP_VendorSpecificProtocol = 0xFF,
};
typedef struct
{
u8 Size;
u8 Type;
}USB_Descriptor_Hdr_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
}USB_StdDescriptor_Hdr_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u16 USBSpecification;
u8 Class;
u8 SubClass;
u8 Protocol;
u8 Endpoint0Size;
u16 VendorID;
u16 ProductID;
u16 ReleaseNumber;
u8 ManufacturerStrIndex;
u8 ProductStrIndex;
u8 SerialNumStrIndex;
u8 NumberOfConfigurations;
}USB_Descriptor_Device_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u16 BcdUSB;
u8 DeviceClass;
u8 DeviceSubClass;
u8 DeviceProtocol;
u8 MaxPacketSize0;
u16 IdVendor;
u16 IdProduct;
u16 BcdDevice;
u8 Manufacturer;
u8 Product;
u8 SerialNumber;
u8 NumConfigurations;
}USB_StdDescriptor_Device_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u16 USBSpecification;
u8 Class;
u8 SubClass;
u8 Protocol;
u8 Endpoint0Size;
u8 NumberOfConfigurations;
u8 Reserved;
}USB_Descriptor_DeviceQualifier_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u16 BcdUSB;
u8 DeviceClass;
u8 DeviceSubClass;
u8 DeviceProtocol;
u8 MaxPacketSize0;
u8 NumConfigurations;
u8 Reserved;
}USB_StdDescriptor_DeviceQualifier_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u16 TotalConfigurationSize;
u8 TotalInterfaces;
u8 ConfigurationNumber;
u8 ConfigurationStrIndex;
u8 ConfigAttributes;
u8 MaxPowerConsumption;
}USB_Descriptor_Configuration_Hdr_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u16 TotalLength;
u8 NumInterfaces;
u8 ConfigurationValue;
u8 Configuration;
u8 MAttributes;
u8 MaxPower;
}USB_StdDescriptor_Configuration_Hdr_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 InterfaceNumber;
u8 AlternateSetting;
u8 TotalEndpoints;
u8 Class;
u8 SubClass;
u8 Protocol;
u8 InterfaceStrIndex;
}USB_Descriptor_Interface_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u8 InterfaceNum;
u8 AlternateSetting;
u8 NumberEndpoints;
u8 InterfaceClass;
u8 InterfaceSubclass;
u8 InterfaceProtocol;
u8 Interface;
}USB_StdDescriptor_Interface_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 FirstInterfaceIndex;
u8 TotalInterfaces;
u8 Class;
u8 SubClass;
u8 Protocol;
u8 IADStrIndex;
}USB_Descriptor_Interface_Association_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u8 FirstInterface;
u8 InterfaceCount;
u8 FunctionClass;
u8 FunctionSubClass;
u8 FunctionProtocol;
u8 Function;
}USB_StdDescriptor_Interface_Association_t;
typedef struct
{
USB_Descriptor_Hdr_t Header;
u8 EndpointAddress;
u8 Attributes;
u16 EndpointSize;
u8 PollingIntervalMS;
}USB_Descriptor_Endpoint_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
u8 EndpointAddress;
u8 MAttributes;
u16 MaxPacketSize;
u8 Interval;
}USB_StdDescriptor_Endpoint_t;
#ifndef __GNUC__
#pragma warning(push)
#pragma warning(disable:4200) // none standard zero length array
#endif
typedef struct
{
USB_Descriptor_Hdr_t Header;
wchar_t UnicodeString[];
}USB_Descriptor_String_t;
typedef struct
{
u8 Length;
u8 DescriptorType;
wchar_t bString[];
}USB_StdDescriptor_String_t;
#ifndef __GNUC__
#pragma warning(pop)
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+872
View File
@@ -0,0 +1,872 @@
/********************************************************************************************************
* @file usb.c
*
* @brief This is the source file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#include "tl_common.h"
#include "drivers.h"
//#define MODULE_USB_ENABLE 1
//#define FLOW_NO_OS 0
//#define USB_MOUSE_ENABLE 1
#if(USB_DESCRIPTER_CONFIGURATION_FOR_KM_DONGLE || USB_ID_AND_STRING_CUSTOM)
#include "../../vendor/8267_multi_mode/dongle_usb.h"
#endif
#ifndef USB_CUSTOM_HID_REPORT_REG_ACCESS
#define USB_CUSTOM_HID_REPORT_REG_ACCESS 1
#endif
#if (MODULE_USB_ENABLE)
#include "usb.h"
#include "usbdesc.h"
#include "application/usbstd/StdRequestType.h"
#if (USB_MOUSE_ENABLE)
#include "application/app/usbmouse_i.h"
#endif
#if (USB_KEYBOARD_ENABLE)
#include "application/app/usbkb_i.h"
#endif
#if (USB_SOMATIC_ENABLE)
#include "application/app/usbsomatic_i.h"
#include "somatic_sensor.h"
#endif
#if (USB_SPEAKER_ENABLE || USB_MIC_ENABLE)
#include "application/app/usbaud_i.h"
#endif
#ifdef WIN32
#include <stdio.h>
#endif
extern u8 keyboard_interface_number, mouse_interface_number;
u8 host_keyboard_status;
u8 host_cmd[8];
u8 host_cmd_pairing_ok = 0;
static USB_Request_Hdr_t control_request;
static u8 * g_response = 0;
static u16 g_response_len = 0;
static int g_stall = 0;
u8 usb_mouse_report_proto = 0; //default 1 for report proto
u8 g_rate = 0; //default 0 for all report
#if (USB_SPEAKER_ENABLE || USB_MIC_ENABLE)
u8 usb_alt_intf[USB_INTF_MAX];
#endif
void usb_send_response(void) {
u16 n;
#ifdef WIN32
n = g_response_len;
#else
if (g_response_len < 8) {
n = g_response_len;
} else {
n = 8;
}
g_response_len -= n;
#endif
usbhw_reset_ctrl_ep_ptr();
while (n-- > 0) {
usbhw_write_ctrl_ep_data(*g_response);
++g_response;
}
}
void usb_prepare_desc_data(void) {
u8 value_l = (control_request.Value) & 0xff;
u8 value_h = (control_request.Value >> 8) & 0xff;
g_response = 0;
g_response_len = 0;
switch (value_h) {
case DTYPE_Device:
#if(USB_ID_AND_STRING_CUSTOM)
g_response = (u8*) (&device_desc_km);
#else
g_response = usbdesc_get_device();
#endif
g_response_len = sizeof(USB_Descriptor_Device_t);
break;
case DTYPE_Configuration:
#if(USB_DESCRIPTER_CONFIGURATION_FOR_KM_DONGLE)
g_response = (u8*) (&configuration_km_desc);
g_response_len = configuration_km_desc[2]; //the third element is the len
#else
g_response = usbdesc_get_configuration();
g_response_len = sizeof(USB_Descriptor_Configuration_t);
#endif
break;
case DTYPE_String:
#if(USB_ID_AND_STRING_CUSTOM)
if (USB_STRING_LANGUAGE == value_l) {
g_response = usbdesc_get_language();
g_response_len = sizeof(LANGUAGE_ID_ENG);
} else if (USB_STRING_VENDOR == value_l) {
g_response = (u8*) (&vendor_desc_km);
g_response_len = vendor_desc_km.Size;
} else if (USB_STRING_PRODUCT == value_l) {
g_response = (u8*) (&prodct_desc_km);
g_response_len = prodct_desc_km.Size;
} else if (USB_STRING_SERIAL == value_l) {
g_response = (u8*) (&serial_desc_km);
g_response_len = serial_desc_km.Size;
#else
if (USB_STRING_LANGUAGE == value_l) {
g_response = usbdesc_get_language();
g_response_len = sizeof(LANGUAGE_ID_ENG);
} else if (USB_STRING_VENDOR == value_l) {
g_response = usbdesc_get_vendor();
g_response_len = sizeof(STRING_VENDOR);
} else if (USB_STRING_PRODUCT == value_l) {
g_response = usbdesc_get_product();
g_response_len = sizeof(STRING_PRODUCT);
} else if (USB_STRING_SERIAL == value_l) {
g_response = usbdesc_get_serial();
g_response_len = sizeof(STRING_SERIAL);
#endif
#if (MS_OS_DESCRIPTOR_ENABLE)
} else if (USB_STRING_MS_OS == value_l) {
g_response = usbdesc_get_OS_descriptor();
g_response_len = sizeof(STRING_MSFT);
#endif
} else {
g_stall = 1;
}
break;
default:
g_stall = 1;
break;
}
if (control_request.Length < g_response_len) {
g_response_len = control_request.Length;
}
return;
}
//standard interface request handle
void usb_handle_std_intf_req() {
u8 value_h = (control_request.Value >> 8) & 0xff;
#if(USB_MIC_ENABLE || USB_SPEAKER_ENABLE || USB_MOUSE_ENABLE || USB_KEYBOARD_ENABLE || USB_SOMATIC_ENABLE)
u8 index_l = (control_request.Index) & 0xff;
#endif
switch (value_h) {
case HID_DTYPE_HID:// HID Descriptor
#if(0)
if (index_l == USB_INTF_AUDIO_HID) {
//audio hid
g_response = usbdesc_get_audio();
g_response_len = sizeof(USB_HID_Descriptor_HID_Audio_t);
}
#endif
#if(USB_MOUSE_ENABLE)
#if(USB_DESCRIPTER_CONFIGURATION_FOR_KM_DONGLE)
if (index_l == mouse_interface_number)
{
g_response = (u8*) (&configuration_desc_mouse[9]);
g_response_len = USB_HID_DESCRIPTOR_LENGTH;
}
#else
if (index_l == USB_INTF_MOUSE) //index_l is the interface number
{
//mouse
g_response = usbdesc_get_mouse();
g_response_len = sizeof(USB_HID_Descriptor_HID_Mouse_t);
}
#endif
#endif
#if(USB_KEYBOARD_ENABLE)
#if(USB_DESCRIPTER_CONFIGURATION_FOR_KM_DONGLE)
if (index_l == keyboard_interface_number)
{
g_response = (u8*) (&configuration_desc_keyboard[9]);
g_response_len = USB_HID_DESCRIPTOR_LENGTH;
}
#else
if (index_l == USB_INTF_KEYBOARD) {
//keyboard
g_response = usbdesc_get_keyboard();
g_response_len = sizeof(USB_HID_Descriptor_HID_Keyboard_t);
}
#endif
#if (AUDIO_HOGP)
if (index_l == USB_INTF_AUDIO_HOGP) {
//keyboard
g_response = usbdesc_get_audio_hogp();
g_response_len = sizeof(USB_HID_Descriptor_HID_Keyboard_t);
}
// if (index_l == USB_INTF_PRINTER) {
// //keyboard
// g_response = usbdesc_get_vendor_desc();
// g_response_len = sizeof(USB_HID_Descriptor_HID_Keyboard_t1);
// }
#endif
#endif
#if(USB_SOMATIC_ENABLE )
if (index_l == USB_INTF_SOMATIC) //index_l is the interface number
{
//SOMATIC
g_response = usbdesc_get_somatic();
g_response_len = sizeof(USB_HID_Descriptor_HID_Somatic_t);
}
#endif
break;
case HID_DTYPE_Report://Report Descriptor
#if (0)
if (index_l == USB_INTF_AUDIO_HID) {
//audio hid
g_response = usbaud_get_report_desc();
g_response_len = usbaud_get_report_desc_size();
}
#endif
#if(USB_KEYBOARD_ENABLE)
if (index_l == (USB_DESCRIPTER_CONFIGURATION_FOR_KM_DONGLE ? keyboard_interface_number : USB_INTF_KEYBOARD)) {
//keyboard
g_response = (u8*) usbkb_get_report_desc();
g_response_len = usbkb_get_report_desc_size();
}
#endif
#if(USB_MOUSE_ENABLE)
else if (index_l == (USB_DESCRIPTER_CONFIGURATION_FOR_KM_DONGLE ? mouse_interface_number : USB_INTF_MOUSE)) {
//mouse
g_response = (u8*) usbmouse_get_report_desc();
g_response_len = usbmouse_get_report_desc_size();
}
#endif
#if (AUDIO_HOGP)
else if(index_l==USB_INTF_AUDIO_HOGP)
{
g_response = (u8*) usbaudio_hogp_get_report_desc();
g_response_len = usbaudio_hogp_get_report_desc_size();
}
// else if(index_l == USB_INTF_PRINTER)
// {
// //cmisc
// g_response = (u8*) usb_vendor_get_report_desc();
// g_response_len = usb_vendor_get_report_desc_size();
// }
#endif
#if(USB_SOMATIC_ENABLE)
else if (index_l == USB_INTF_SOMATIC) {
//somatic sensor
g_response = (u8*) usbsomatic_get_report_desc();
g_response_len = usbsomatic_get_report_desc_size();
}
#endif
#if (!(USB_MOUSE_ENABLE | USB_KEYBOARD_ENABLE | USB_SOMATIC_ENABLE))
if (0) {
}
#endif
else{
g_stall = 1;
}
break;
case 0x23:// Phisical Descriptor
// TODO
break;
default:// other condition
break;
}
if (control_request.Length < g_response_len) {
g_response_len = control_request.Length;
}
return;
}
u32 custom_read_dat;
u32 custom_reg_cmd;
void usb_handle_out_class_intf_req(int data_request) {
u8 property = control_request.Request;
u8 value_l = (control_request.Value) & 0xff;
u8 value_h = (control_request.Value >> 8) & 0xff;
#if (USB_MIC_ENABLE || USB_SPEAKER_ENABLE)
u8 Entity = (control_request.Index >> 8) & 0xff;
#endif
switch (property) {
case HID_REQ_SetReport:
switch (value_h) {
case HID_REPORT_ITEM_In:
break;
case HID_REPORT_ITEM_Out:
// usb_hid_set_report_ouput();
break;
case HID_REPORT_ITEM_Feature:
if (data_request) {
host_keyboard_status = usbhw_read_ctrl_ep_data();
}
#if(USB_SET_REPORT_FEATURE_SUPPORT)
{
usb_set_report_t rpt;
rpt.report_id = value_l;
rpt.len = control_request.Index;
ev_emit_event_syn(EV_USB_SET_REPORT, (void*)(&rpt)); // send in report id
}
#endif
break;
case HID_REPORT_CUSTOM:
#if (USB_CUSTOM_HID_REPORT)
{ //pairing, EMI-TX, EMI-RX
if (data_request) {
int i=0;
usbhw_reset_ctrl_ep_ptr (); //address
for(i=0;i<8;i++) {
host_cmd[i] = usbhw_read_ctrl_ep_data();
}
#if (USB_CUSTOM_HID_REPORT_REG_ACCESS)
custom_reg_cmd = (host_cmd[1] & 0xf0) == 0xc0;
if (custom_reg_cmd) {
host_cmd[0] = 0;
int adr = *((u16 *)(host_cmd + 2));
int len = host_cmd[1] & 3;
if (host_cmd[1] == 0xcc && adr == 0x5af0) { //re-enumerate device
usb_dp_pullup_en (0); //disable device
sleep_us (300000);
reg_ctrl_ep_irq_mode = 0xff; //hardware mode
usb_dp_pullup_en (1); //enable device
}
else {
adr += 0x800000;
}
if ((host_cmd[1] & 0x0c)==0) { //write core register
if (len == 0) {
for (int k=0; k<4; k++) {
custom_read_dat = (custom_read_dat >> 8) | (read_reg8 (adr++) << 24);
}
}
else if (len == 1) {
write_reg8 (adr, host_cmd[4]);
}
else if (len == 2) {
write_reg16 (adr, *((u16 *)(host_cmd + 4)));
}
else {
write_reg32 (adr, *((u32 *)(host_cmd + 4)));
}
}
else { //read core register
if (len == 0) {
custom_read_dat = analog_read_reg8 (host_cmd[2]);
}
else {
analog_write_reg8 (host_cmd[2], host_cmd[4]);
}
}
}
#endif
}
break;
}
#endif
default:
g_stall = 1;
break;
}
break;
case HID_REQ_SetIdle:
if (data_request) {
g_rate = usbhw_read_ctrl_ep_data();
}
g_rate = value_h;
break;
case HID_REQ_SetProtocol:
if (data_request) {
usb_mouse_report_proto = usbhw_read_ctrl_ep_data();
}
usb_mouse_report_proto = value_l;
reg_usb_ep_ctrl(USB_EDP_MOUSE) = 0;
break;
default:
g_stall = 1;
break;
}
#if (USB_MIC_ENABLE || USB_SPEAKER_ENABLE)
if(0 == g_stall){ // already handled
return;
}
g_stall = 0;
switch(Entity){
case USB_SPEAKER_FEATURE_UNIT_ID:
usbaud_handle_set_speaker_cmd(value_h);
break;
case USB_MIC_FEATURE_UNIT_ID:
usbaud_handle_set_mic_cmd(value_h);
break;
default:
g_stall = 1;
break;
}
#endif
}
void usb_handle_in_class_intf_req() {
u8 property = control_request.Request;
#if (USB_MIC_ENABLE || USB_SPEAKER_ENABLE)
u8 value_h = (control_request.Value >> 8);
u8 Entity = (control_request.Index >> 8);
#endif
switch (property) {
case 0x00:
usbhw_write_ctrl_ep_data(0x00);
break;
case HID_REQ_GetReport:
#if(USB_SOMATIC_ENABLE)
if(usbsomatic_hid_report_type((control_request.Value & 0xff))){
}
else
#elif (USB_CUSTOM_HID_REPORT)
if( control_request.Value==0x0305 ) {
if (USB_CUSTOM_HID_REPORT_REG_ACCESS && custom_reg_cmd) {
usbhw_write_ctrl_ep_data (custom_read_dat);
usbhw_write_ctrl_ep_data (custom_read_dat>>8);
usbhw_write_ctrl_ep_data (custom_read_dat>>16);
usbhw_write_ctrl_ep_data (custom_read_dat>>24);
usbhw_write_ctrl_ep_data (0x10);
usbhw_write_ctrl_ep_data (0x20);
usbhw_write_ctrl_ep_data (0x40);
usbhw_write_ctrl_ep_data (0x80);
}
else {
usbhw_write_ctrl_ep_data (0x04);
usbhw_write_ctrl_ep_data (0x58);
usbhw_write_ctrl_ep_data (0x00);
usbhw_write_ctrl_ep_data (host_cmd_pairing_ok ? 0xa1 : 0x00); //For binding OK
usbhw_write_ctrl_ep_data (0x00);
usbhw_write_ctrl_ep_data (0x00);
usbhw_write_ctrl_ep_data (0x08);
usbhw_write_ctrl_ep_data (0x00);
}
}
else
#endif
{ // donot know what is this
// usbhw_write_ctrl_ep_data(0x81);
// usbhw_write_ctrl_ep_data(0x02);
// usbhw_write_ctrl_ep_data(0x55);
// usbhw_write_ctrl_ep_data(0x55);
}
break;
case HID_REQ_GetIdle:
usbhw_write_ctrl_ep_data(g_rate);
break;
case HID_REQ_GetProtocol:
usbhw_write_ctrl_ep_data(usb_mouse_report_proto);
break;
default:
g_stall = 1;
break;
}
#if (USB_MIC_ENABLE || USB_SPEAKER_ENABLE)
if(0 == g_stall){ // already handled
return;
}
g_stall = 0;
switch(Entity){
case USB_SPEAKER_FEATURE_UNIT_ID:
if(usbaud_handle_get_speaker_cmd(property, value_h)){
g_stall = 1;
}
break;
case USB_MIC_FEATURE_UNIT_ID:
if(usbaud_handle_get_mic_cmd(property, value_h)){
g_stall = 1;
}
break;
default:
g_stall = 1;
break;
}
#endif
}
void usb_handle_in_class_endp_req() {
#if (USB_MIC_ENABLE || USB_SPEAKER_ENABLE)
u8 property = control_request.Request;
u8 ep_ctrl = control_request.Value >> 8;
//u8 addr = (control_request.Index >> 8);
if(ep_ctrl == AUDIO_EPCONTROL_SamplingFreq){
switch(property){
case AUDIO_REQ_GetCurrent:
usbhw_write_ctrl_ep_data(MIC_SAMPLE_RATE & 0xff);
usbhw_write_ctrl_ep_data(MIC_SAMPLE_RATE >> 8);
usbhw_write_ctrl_ep_data(MIC_SAMPLE_RATE >> 16);
break;
default:
break;
}
}
#endif
}
void usb_handle_out_class_endp_req(int data_request) {
return;
#if 0
u8 property = control_request.Request;
u8 ep_ctrl = control_request.Value & 0xff;
#if (USB_MIC_ENABLE || USB_SPEAKER_ENABLE)
u8 addr = (control_request.Index >> 8);
#endif
#endif
}
void usb_handle_set_intf() {
#if (USB_SPEAKER_ENABLE || USB_MIC_ENABLE)
u8 value_l = (control_request.Value) & 0xff;
u8 intf_index = (control_request.Index) & 0x07;
usb_alt_intf[intf_index] = value_l;
#if (USB_MIC_ENABLE)
if(USB_INTF_MIC == intf_index && value_l){
// usbhw_reset_ep_ptr(USB_EDP_MIC);
// reg_usb_ep_ptr(USB_EDP_MIC) = USB_MIC_CHANNELS_LEN;
// reg_usb_ep_ctrl(USB_EDP_MIC) = (MIC_CHANNEL_COUNT == 2 ? 0x81 : 0xc1);
reg_usb_ep_ptr(USB_EDP_MIC) = 0;
reg_usb_ep_ctrl(USB_EDP_MIC) = BIT(0); //ACK first packet
}
#endif
#if (USB_SPEAKER_ENABLE)
if(USB_INTF_SPEAKER == intf_index && value_l){
// usbhw_reset_ep_ptr(USB_EDP_MIC);
// reg_usb_ep_ptr(USB_EDP_MIC) = USB_MIC_CHANNELS_LEN;
// reg_usb_ep_ctrl(USB_EDP_MIC) = (MIC_CHANNEL_COUNT == 2 ? 0x81 : 0xc1);
reg_usb_ep_ptr(USB_EDP_SPEAKER) = 0;
reg_usb_ep_ctrl(USB_EDP_SPEAKER) = BIT(0); //ACK first packet
}
#endif
#endif
return;
}
#if (USB_SPEAKER_ENABLE || USB_MIC_ENABLE)
void usb_handle_get_intf() {
u8 intf_index = (control_request.Index) & 0x07;
usbhw_write_ctrl_ep_data(usb_alt_intf[intf_index]);
return;
}
#endif
void usb_handle_request(u8 data_request) {
u8 RequestType = control_request.RequestType;
u8 Request = control_request.Request;
#ifdef WIN32
printf("\r\nusb_sim:s:");
#endif
usbhw_reset_ctrl_ep_ptr();
switch (RequestType) {
case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE):
if (REQ_GetDescriptor == Request) {
if (USB_IRQ_SETUP_REQ == data_request) {
usb_prepare_desc_data();
}
usb_send_response();
}
break;
case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE):
if (REQ_GetDescriptor == Request) {
if (USB_IRQ_SETUP_REQ == data_request) {
usb_handle_std_intf_req();
}
usb_send_response();
}
#if (USB_SPEAKER_ENABLE || USB_MIC_ENABLE)
else if (REQ_GetInterface == Request) {
usb_handle_get_intf();
}
#endif
break;
#if (MS_OS_DESCRIPTOR_ENABLE)
case (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_DEVICE):
case (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_INTERFACE):
if ((Request == MS_VENDORCODE)) {//Retrieve an OS Feature Descriptor
u8 index_l = control_request.Index&0xff;
if (USB_IRQ_SETUP_REQ == data_request) {
//usb_indexl==0x04 for Extended compat ID
//usb_indexl==0x05 for Extended properties
if(index_l==0x04 )
{
g_response = usbdesc_get_compatID(&g_response_len);
}
else if(index_l==0x05)
{
g_response = usbdesc_get_OSFeature(&g_response_len);
}
else
g_stall = 1;
if (control_request.Length < g_response_len) {
g_response_len = control_request.Length;
}
}
usb_send_response();
}
break;
#endif
case (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE):
usb_handle_out_class_intf_req(data_request);
break;
case (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_ENDPOINT):
usb_handle_out_class_endp_req(data_request);
break;
case (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE):
usb_handle_in_class_intf_req();
break;
case (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_ENDPOINT):
usb_handle_in_class_endp_req();
break;
case (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE):
if (REQ_SetInterface == Request) {
usb_handle_set_intf();
}
break;
default:
g_stall = 1;
break;
}
return;
}
void usb_handle_ctl_ep_setup() {
usbhw_reset_ctrl_ep_ptr();
control_request.RequestType = usbhw_read_ctrl_ep_data();
control_request.Request = usbhw_read_ctrl_ep_data();
control_request.Value = usbhw_read_ctrl_ep_u16();
control_request.Index = usbhw_read_ctrl_ep_u16();
control_request.Length = usbhw_read_ctrl_ep_u16();
g_stall = 0;
usb_handle_request(USB_IRQ_SETUP_REQ);
if (g_stall)
usbhw_write_ctrl_ep_ctrl(FLD_EP_DAT_STALL);
else
usbhw_write_ctrl_ep_ctrl(FLD_EP_DAT_ACK);
}
void usb_handle_ctl_ep_data(void) {
usbhw_reset_ctrl_ep_ptr();
g_stall = 0;
usb_handle_request(USB_IRQ_DATA_REQ);
if (g_stall)
usbhw_write_ctrl_ep_ctrl(FLD_EP_DAT_STALL);
else
usbhw_write_ctrl_ep_ctrl(FLD_EP_DAT_ACK);
}
void usb_handle_ctl_ep_status() {
if (g_stall)
usbhw_write_ctrl_ep_ctrl(FLD_EP_STA_STALL);
else
usbhw_write_ctrl_ep_ctrl(FLD_EP_STA_ACK);
}
u8 usb_has_suspend_irq = 0;
u8 usb_just_wakeup_from_suspend = 1;
extern u8 rf_channel;
int usb_suspend_check(void){
return 0;
}
#if(0)
void usb_resume_host(void)
{
#if (MCU_CORE_TYPE == MCU_CORE_3520)
#else
reg_wakeup_en = FLD_WAKEUP_SRC_USB_RESM;
reg_wakeup_en = 0;
#endif
sleep_us(6000);
}
#endif
u8 edp_toggle[8];
void usb_handle_irq(void)
{
u32 irq = usbhw_get_ctrl_ep_irq();
if (irq & FLD_CTRL_EP_IRQ_SETUP) {
usbhw_clr_ctrl_ep_irq(FLD_CTRL_EP_IRQ_SETUP);
usb_handle_ctl_ep_setup();
}
if (irq & FLD_CTRL_EP_IRQ_DATA) {
usbhw_clr_ctrl_ep_irq(FLD_CTRL_EP_IRQ_DATA);
usb_handle_ctl_ep_data();
}
if (irq & FLD_CTRL_EP_IRQ_STA) {
usbhw_clr_ctrl_ep_irq(FLD_CTRL_EP_IRQ_STA);
usb_handle_ctl_ep_status();
}
if (reg_usb_irq_mask & FLD_USB_IRQ_RESET_O){ //USB reset
usb_mouse_report_proto = 1;
reg_usb_irq_mask |= FLD_USB_IRQ_RESET_O; //Clear USB reset flag
for (int i=0; i<8; i++) {
reg_usb_ep_ctrl(i) = 0;
edp_toggle[i]=0;
}
}
irq = reg_usb_irq; // data irq
#if(USB_SOMATIC_ENABLE)
if(irq & BIT((USB_EDP_SOMATIC_OUT & 0x07))){
reg_usb_irq = BIT((USB_EDP_SOMATIC_OUT & 0x07)); // clear ime
usbhw_reset_ep_ptr(USB_EDP_SOMATIC_OUT);
ev_emit_event_syn(EV_USB_OUT_DATA, (void*)irq);
usbhw_data_ep_ack(USB_EDP_SOMATIC_OUT);
}
#endif
if(IRQ_USB_PWDN_ENABLE && (reg_irq_src(FLD_IRQ_USB_PWDN_EN) & FLD_IRQ_USB_PWDN_EN)){
usb_has_suspend_irq = 1;
}else{
usb_has_suspend_irq = 0;
}
#if (AUDIO_HOGP)
// if(irq & BIT(USB_EDP_KEYBOARD_OUT & 0x07)){
// reg_usb_irq = BIT((USB_EDP_KEYBOARD_OUT & 0x07)); // clear ime
//
// g_stall = 0;
// u8 rx_from_usbhost_len = reg_usb_ep_ptr(USB_EDP_KEYBOARD_OUT);
// usbhw_reset_ep_ptr(USB_EDP_KEYBOARD_OUT);
//
// if(rx_from_usbhost_len > 0 && rx_from_usbhost_len <= 64){
// keyboard_outpoint_handle(rx_from_usbhost_len);
// }
//
// if(g_stall)
// { usbhw_data_ep_stall(USB_EDP_KEYBOARD_OUT); }
// else
// { usbhw_data_ep_ack(USB_EDP_KEYBOARD_OUT); }
// }
if(irq & BIT((USB_EDP_AUDIO_IN & 0x07)))
{
reg_usb_irq = BIT((USB_EDP_AUDIO_IN & 0x07)); // clear ime
// usbhw_reset_ep_ptr(USB_EDP_AUDIO_IN);
}
// if(irq & BIT((USB_EDP_PRINTER_OUT & 0x07)))
// {
// reg_usb_irq = BIT((USB_EDP_PRINTER_OUT & 0x07)); // clear ime
// usbhw_reset_ep_ptr(USB_EDP_PRINTER_OUT);
// }
if(IRQ_USB_PWDN_ENABLE && (reg_irq_src & FLD_IRQ_USB_PWDN_EN)){
usb_has_suspend_irq = 1;
}else{
usb_has_suspend_irq = 0;
}
#endif
#if (!USB_DESCRIPTER_CONFIGURATION_FOR_KM_DONGLE)
if ((reg_irq_src(FLD_IRQ_USB_PWDN_EN) & FLD_IRQ_USB_PWDN_EN))
{
return;
}
#if(USB_MOUSE_ENABLE)
extern void usbmouse_report_frame(void);
extern void usbmouse_release_check(void);
usbmouse_report_frame();
//usbmouse_release_check();
#endif
#if(USB_KEYBOARD_ENABLE)
extern void usbkb_report_frame(void);
extern void usbkb_release_check(void);
//usbkb_report_frame();
//usbkb_release_check();
#endif
#endif
usb_hid_report_fifo_proc();
}
void usb_init_interrupt(void)
{
usbhw_enable_manual_interrupt(FLD_CTRL_EP_AUTO_STD | FLD_CTRL_EP_AUTO_DESC);
reg_usb_edp_en = 0xff;//todo by zhangchong
reg_usb_irq_mask |= BIT(0); //set USB IRQ reset mask
}
void usb_init(void)
{
usb_init_interrupt();
}
#endif
+80
View File
@@ -0,0 +1,80 @@
/********************************************************************************************************
* @file usb.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include "tl_common.h"
#include "drivers.h"
#include "usbdesc.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
enum {
// 3000 ms
USB_TIME_BEFORE_ALLOW_SUSPEND = (3000*1000),
};
enum {
USB_IRQ_SETUP_REQ = 0,
USB_IRQ_DATA_REQ,
};
// telink usb report ctrl command. used mixed with USB_AUD_PLAY_PAUSE...
enum{
USB_REPORT_NO_EVENT = 0xf0,
USB_REPORT_RELEASE = 0xff,
};
#if (USB_MIC_ENABLE)
extern u8 usb_alt_intf[USB_INTF_MAX];
static inline int usb_mic_is_enable(){
return usb_alt_intf[USB_INTF_MIC];
}
#endif
extern u8 usb_just_wakeup_from_suspend;
extern u8 usb_has_suspend_irq;
extern u8 edp_toggle[8];
void usb_init(void);
void usb_handle_irq(void);
#ifndef USB_SOFTWARE_CRC_CHECK
#define USB_SOFTWARE_CRC_CHECK 0
#endif
#define MS_VENDORCODE 'T' //This must match the char after the "MSFT100"
#define STRING_MSFT L"MSFT100T"
#define MS_OS_DESCRIPTOR_ENABLE 0
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+822
View File
@@ -0,0 +1,822 @@
/********************************************************************************************************
* @file usbdesc.c
*
* @brief This is the source file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#include <application/usbstd/usbdesc.h>
#include "tl_common.h"
#include "drivers.h"
#if (USB_MOUSE_ENABLE)
#include <application/app/usbmouse_i.h>
#endif
#if (USB_KEYBOARD_ENABLE)
#include <application/app/usbkb_i.h>
#endif
#if (USB_SOMATIC_ENABLE)
#include "../app/usbsomatic_i.h"
#endif
#if (USB_SPEAKER_ENABLE || USB_MIC_ENABLE)
#include <application/app/usbaud_i.h>
#endif
#if (USB_CDC_ENABLE)
#include <application/app/usbcdc_i.h>
#endif
//#include "usb.h"
// request parameters
/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
* the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
* via the language ID table available at USB.org what languages the device supports for its string descriptors.
*/
const USB_Descriptor_String_t language_desc = { {
sizeof(USB_Descriptor_Hdr_t) + 2, DTYPE_String },
{ LANGUAGE_ID_ENG } };
/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
* form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
* Descriptor.
*/
const USB_Descriptor_String_t vendor_desc = { { sizeof(USB_Descriptor_Hdr_t)
+ sizeof(STRING_VENDOR) - 2, DTYPE_String }, // Header
STRING_VENDOR };
/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
* and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
* Descriptor.
*/
const USB_Descriptor_String_t product_desc = { {
sizeof(USB_Descriptor_Hdr_t) + sizeof(STRING_PRODUCT) - 2,
DTYPE_String }, // Header
STRING_PRODUCT };
/** Serial number string. This is a Unicode string containing the device's unique serial number, expressed as a
* series of uppercase hexadecimal digits.
*/
const USB_Descriptor_String_t serial_desc = { { sizeof(USB_Descriptor_Hdr_t)
+ sizeof(STRING_SERIAL) - 2, DTYPE_String }, // Header
STRING_SERIAL };
#if (MS_OS_DESCRIPTOR_ENABLE)
const USB_Descriptor_String_t microsoft_OS_desc = { {
sizeof(USB_Descriptor_Hdr_t) + sizeof(STRING_MSFT) - 2,
DTYPE_String }, // Header
STRING_MSFT };
const unsigned char OSFeatureDescriptor[] ={
0x26,0x01, 0x00, 0x00,
0x00,0x01,
0x05,0x00,
0x05,0x00,
// DeviceIdleEnabled
0x36,0x00, 0x00, 0x00,
0x04,0x00, 0x00, 0x00,
0x24, 0x00,
0x44,0x00,0x65,0x00,0x76,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x49,0x00,0x64,0x00,
0x6C,0x00,0x65,0x00,0x45,0x00,0x6E,0x00,0x61,0x00,0x62,0x00,0x6C,0x00,0x65,0x00,
0x64,0x00,0x00,0x00,
0x04,0x00,0x00,0x00,
0x01,0x00,0x00,0x00,
//DefaultIdleState
0x34,0x00,0x00,0x00,
0x04,0x00, 0x00, 0x00,
0x22,0x00,
0x44,0x00, 0x65,0x00, 0x66,0x00, 0x61,0x00, 0x75,0x00,
0x6C,0x00, 0x74,0x00, 0x49,0x00, 0x64,0x00, 0x6C,0x00,
0x65,0x00, 0x53,0x00, 0x74,0x00, 0x61,0x00, 0x74,0x00,
0x65,0x00, 0x00,0x00,
0x04,0x00,0x00,0x00,
0x01,0x00,0x00,0x00,
//default timeout value for selective suspend.
0x38,0x00,0x00,0x00,
0x04,0x00, 0x00, 0x00,
0x26,0x00,
0x44,0x00,0x65,0x00,0x66,0x00,0x61,0x00,
0x75,0x00,0x6C,0x00,0x74,0x00,0x49,0x00,
0x64,0x00,0x6C,0x00,0x65,0x00,0x54,0x00,
0x69,0x00,0x6D,0x00,0x65,0x00,0x6F,0x00,
0x75,0x00,0x74,0x00,
0x00,0x00,
0x04,0x00,0x00,0x00,
0x88,0x13,0x00,0x00,
// user-enabled selective suspend.
0x44,0x00,0x00,0x00,
0x04,0x00, 0x00, 0x00,
0x32,0x00,
0x55,0x00,0x73,0x00,
0x65,0x00,0x72,0x00,
0x53,0x00,0x65,0x00,
0x74,0x00,0x44,0x00,
0x65,0x00,0x76,0x00,
0x69,0x00,0x63,0x00,
0x65,0x00,0x49,0x00,
0x64,0x00,0x6C,0x00,
0x65,0x00,0x45,0x00,
0x6E,0x00,0x61,0x00,
0x62,0x00,0x6C,0x00,
0x65,0x00,0x64,0x00,
0x00,0x00,
0x04,0x00,0x00,0x00,
0x01,0x00,0x00,0x00,
//user-enabled remote wake setting.
0x36,0x00,0x00,0x00,
0x04,0x00,0x00,0x00,
0x24,0x00,
0x53,0x00,0x79,0x00,0x73,0x00,0x74,0x00,0x65,0x00,0x6D,0x00,0x57,0x00,0x61,0x00,
0x6B,0x00,0x65,0x00,0x45,0x00,0x6E,0x00,0x61,0x00,0x62,0x00,0x6C,0x00,0x65,0x00,
0x64,0x00,0x00,0x00,
0x04,0x00,0x00,0x00,
0x01,0x00,0x00,0x00
};
const USB_MS_OS_compatID_t OSFeatureDescriptor_compatID = {
{
sizeof(USB_MS_OS_compatID_Header_t)
+ USB_KEYBOARD_ENABLE * sizeof(USB_MS_OS_compatID_Function_t)
+ USB_MOUSE_ENABLE * sizeof(USB_MS_OS_compatID_Function_t),
0x0100,
0x0004,
USB_KEYBOARD_ENABLE + USB_MOUSE_ENABLE,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,
},
{
#if USB_KEYBOARD_ENABLE
{
USB_INTF_KEYBOARD,
0x01,
'W', 'I', 'N', 'U' ,'S','B', 0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
},
#endif
#if USB_MOUSE_ENABLE
{
USB_INTF_MOUSE,
0x01,
'W', 'I', 'N', 'U' ,'S','B', 0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
},
#endif
}
};
#if 0
const unsigned char OSFeatureDescriptor_compatID[] = {
0x28,0x00,0x00,0x00,
0x00,0x01,
0x04,0x00,
0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,
USB_INTF_MOUSE,
0x01,
'W', 'I', 'N', 'U' ,'S','B', 0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
};
#endif
#endif
#ifndef ID_PRODUCT
#define ID_PRODUCT (ID_PRODUCT_BASE | (USB_PRINTER_ENABLE?(1<<0):0) | (USB_SPEAKER_ENABLE?(1<<1):0) | (USB_MIC_ENABLE?(1<<2):0) \
| (USB_MOUSE_ENABLE?(1<<3):0) | (USB_KEYBOARD_ENABLE?(1<<4):0) | (USB_SOMATIC_ENABLE?(1<<5):0))
#endif
const USB_Descriptor_Device_t device_desc = { {
sizeof(USB_Descriptor_Device_t), DTYPE_Device }, // Header
#if (MS_OS_DESCRIPTOR_ENABLE)
0x0200, // USBSpecification, USB 2.0
#else
0x0110, // USBSpecification, USB 1.1
#endif
#if (USB_CDC_ENABLE)
CDC_CSCP_CDCClass, // Class
USB_CSCP_NoDeviceSubclass, // SubClass
USB_CSCP_NoDeviceProtocol, // Protocol
#else
USB_CSCP_NoDeviceClass,
USB_CSCP_NoDeviceSubclass, // SubClass
USB_CSCP_NoDeviceProtocol, // Protocol
#endif
8, // Endpoint0Size, Maximum Packet Size for Zero Endpoint. Valid Sizes are 8, 16, 32, 64
ID_VENDOR, // VendorID
#if USB_CDC_ENABLE
0x8846,
#else
#if AUDIO_HOGP
0xc080,//ID_PRODUCT, // ProductID
#else
ID_PRODUCT,
#endif
#endif
0x0100, // .ReleaseNumber
USB_STRING_VENDOR, // .ManufacturerStrIndex
USB_STRING_PRODUCT, // .ProductStrIndex
3, // .SerialNumStrIndex, iSerialNumber
1 };
const USB_Descriptor_Configuration_t
configuration_desc = { { {
sizeof(USB_Descriptor_Configuration_Hdr_t),
DTYPE_Configuration }, // Length, type
sizeof(USB_Descriptor_Configuration_t), // TotalLength: variable
USB_INTF_MAX, // NumInterfaces
1, // Configuration index
NO_DESCRIPTOR, // Configuration String
//USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP, // Attributes
USB_CONFIG_ATTR_RESERVED,//don't support remote wakeup
USB_CONFIG_POWER_MA(250) // MaxPower = 2*250mA
},
#if AUDIO_HOGP
// HID audio hogp interface
{ {sizeof(USB_Descriptor_Interface_t), DTYPE_Interface},
USB_INTF_AUDIO_HOGP,
0, // AlternateSetting
1, // bNumEndpoints
HID_CSCP_HIDClass, HID_CSCP_NonBootSubclass,
HID_CSCP_KeyboardBootProtocol, NO_DESCRIPTOR
},
{
// hid des
{
{sizeof(USB_HID_Descriptor_HID_t), HID_DTYPE_HID}, 0x0111, // HIDSpec
0, 1, // TotalReportDescriptors
HID_DTYPE_Report, {sizeof(audio_hogp_report_desc), 0x00}, // HIDReportLength
},
// audio_hogp_in_endpoint
{
{sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint},
ENDPOINT_DIR_IN | USB_EDP_AUDIO_IN,
EP_TYPE_INTERRUPT, 0x40, // EndpointSize
1,//USB_KEYBOARD_POLL_INTERVAL // PollingIntervalMS
},
// // audio_hogp_out_endpoint
// {
// {sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint},
// ENDPOINT_DIR_OUT | USB_EDP_KEYBOARD_OUT,
// EP_TYPE_BULK, 0x0010, // EndpointSize
// 1//USB_KEYBOARD_POLL_INTERVAL // PollingIntervalMS
// },
},
#endif
#if (USB_CDC_ENABLE)
#if 0
{
// iad0
{sizeof(USB_Descriptor_Interface_Association_t), DTYPE_InterfaceAssociation}, // Header
0, // FirstInterfaceIndex
2, // TotalInterface
CDC_CSCP_CDCClass, // Class
CDC_CSCP_ACMSubclass, // Subclass
CDC_CSCP_ATCommandProtocol, // protocol
NO_DESCRIPTOR // IADStrIndex
},
#endif
{
// cdc_interface
{sizeof(USB_Descriptor_Interface_t), DTYPE_Interface}, // Header
USB_INTF_CDC_CCI, // InterfaceNumber
0, // AlternateSetting
1, // TotalEndpoints
CDC_CSCP_CDCClass, // Class
CDC_CSCP_ACMSubclass, // SubClass
CDC_CSCP_ATCommandProtocol, // Protocol
NO_DESCRIPTOR //InterfaceStrIndex
},
{
// cdc_descriptor
//CDC_Functional_Header
{
{sizeof(USB_CDC_Descriptor_FunctionalHeader_t), DTYPE_CSInterface}, // Header
CDC_DSUBTYPE_CSInterface_Header, // Subtype
0x0110 // CDCSpecification
},
// CDC_Functional_ACM =
{
{sizeof(USB_CDC_Descriptor_FunctionalACM_t), DTYPE_CSInterface}, // Header
CDC_DSUBTYPE_CSInterface_ACM, // Subtype
0x02 // Capabilities
},
// CDC_Functional_Union =
{
{sizeof(USB_CDC_Descriptor_FunctionalUnion_t), DTYPE_CSInterface}, // Header
CDC_DSUBTYPE_CSInterface_Union, // Subtype
0, // MasterInterfaceNumber
1, // SlaveInterfaceNumber
},
// CDC_CallManagement =
{
{sizeof(USB_CDC_Descriptor_FunctionalUnion_t), DTYPE_CSInterface}, // Header
CDC_DSUBTYPE_CSInterface_CallManagement, // Subtype
0, // MasterInterfaceNumber
1, // SlaveInterfaceNumber
},
// CDC_NotificationEndpoint =
{
{sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint}, // Header
(ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM), // EndpointAddress
(EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), // Attributes
CDC_NOTIFICATION_EPSIZE, // EndpointSize
0x40 // PollingIntervalMS
},
// CDC_DCI_Interface =
{
{sizeof(USB_Descriptor_Interface_t), DTYPE_Interface}, // Header
USB_INTF_CDC_DCI, // InterfaceNumber
0, // AlternateSetting
2, // TotalEndpoints
CDC_CSCP_CDCDataClass, // Class
CDC_CSCP_NoDataSubclass, // SubClass
CDC_CSCP_NoDataProtocol, // Protocol
NO_DESCRIPTOR // InterfaceStrIndex
},
// CDC_DataOutEndpoint =
{
{sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint}, // Header
(ENDPOINT_DIR_OUT | CDC_RX_EPNUM), // EndpointAddress
(EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), // Attributes
CDC_TXRX_EPSIZE, // EndpointSize
0x00 // PollingIntervalMS
},
// CDC_DataInEndpoint =
{
{sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint}, // Header
(ENDPOINT_DIR_IN | CDC_TX_EPNUM), // EndpointAddress
(EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), // Attributes
CDC_TXRX_EPSIZE, // EndpointSize
0x00 // PollingIntervalMS
},
},
#endif
#if(USB_PRINTER_ENABLE)
// printer_interface
{ { sizeof(USB_Descriptor_Interface_t), DTYPE_Interface },
USB_INTF_PRINTER, 0, // AlternateSetting
#if(USB_SOMATIC_ENABLE)
1, // bNumEndpoints
#else
2, // bNumEndpoints
#endif
PRNT_CSCP_PrinterClass, // bInterfaceclass ->Printer
PRNT_CSCP_PrinterSubclass, // bInterfaceSubClass -> Control
PRNT_CSCP_BidirectionalProtocol,// bInterfaceProtocol
NO_DESCRIPTOR // iInterface, same as iProduct in USB_Descriptor_Device_t, or else not working
},
// printer_in_endpoint
{ { sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint }, // length, bDescriptorType
ENDPOINT_DIR_IN | USB_EDP_PRINTER_IN, // endpoint id
EP_TYPE_BULK, // endpoint type
0x0040, // wMaxPacketSize
0 // bInterval
},
#if(!USB_SOMATIC_ENABLE)
// printer_out_endpoint
{ { sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint }, // length, bDescriptorType
USB_EDP_PRINTER_OUT, // endpoint id
EP_TYPE_BULK, // endpoint type
0x0040, // wMaxPacketSize
0 // polling bInterval. valid for iso or interrupt type
},
#endif
#endif
#if (USB_MIC_ENABLE || USB_SPEAKER_ENABLE)
// audio_control_interface
{ { sizeof(USB_Descriptor_Interface_t), DTYPE_Interface},
USB_INTF_AUDIO_CONTROL, 0, // AlternateSetting
0, // bNumEndpoints
AUDIO_CSCP_AudioClass, // bInterfaceclass ->Printer
AUDIO_CSCP_ControlSubclass, // bInterfaceSubClass -> Control
AUDIO_CSCP_ControlProtocol, // bInterfaceProtocol
NO_DESCRIPTOR // iInterface
},
// audio_control_interface_ac;
{
#if (USB_MIC_ENABLE && USB_SPEAKER_ENABLE)
{ sizeof(USB_Audio_Descriptor_Interface_AC_TL_t),DTYPE_CSInterface}, AUDIO_DSUBTYPE_CSInterface_Header, // Subtype
{0x00, 0x01}, // ACSpecification, version == 1.0
// debug note: TotalLength must less than 256
{(sizeof(USB_Audio_Descriptor_Interface_AC_TL_t) + /*10*/
sizeof(USB_Audio_Descriptor_InputTerminal_t) + /*12*/
sizeof(USB_Audio_Descriptor_OutputTerminal_t) + /*9*/
sizeof(USB_Audio_Descriptor_FeatureUnit_Mic_t) + /*9*/
sizeof(USB_Audio_Descriptor_InputTerminal_t) + /*12*/
sizeof(USB_Audio_Descriptor_OutputTerminal_t) + /*9*/
sizeof(USB_Audio_StdDescriptor_FeatureUnit_t)/*10*/), 0}, 2, // InCollection
USB_INTF_SPEAKER, USB_INTF_MIC
#else
{sizeof(USB_Audio_Descriptor_Interface_AC_t), DTYPE_CSInterface},
AUDIO_DSUBTYPE_CSInterface_Header, // Subtype
{0x00, 0x01}, // ACSpecification, version == 1.0
#if (USB_MIC_ENABLE)
{(sizeof(USB_Audio_Descriptor_Interface_AC_t) + /*9*/
sizeof(USB_Audio_Descriptor_InputTerminal_t) + /*12*/
sizeof(USB_Audio_Descriptor_OutputTerminal_t) + /*9*/
sizeof(USB_Audio_Descriptor_FeatureUnit_Mic_t) /*9*/),0},
1,
USB_INTF_MIC
#else
{(sizeof(USB_Audio_Descriptor_Interface_AC_t) + /*9*/
sizeof(USB_Audio_Descriptor_InputTerminal_t) + /*12*/
sizeof(USB_Audio_Descriptor_OutputTerminal_t) + /*9*/
sizeof(USB_Audio_StdDescriptor_FeatureUnit_t) /*10*/),0},
1,
USB_INTF_SPEAKER
#endif
#endif
},
#endif
#if (USB_SPEAKER_ENABLE)
// speaker_input_terminal
{ { sizeof(USB_Audio_Descriptor_InputTerminal_t), DTYPE_CSInterface},
AUDIO_DSUBTYPE_CSInterface_InputTerminal,
USB_SPEAKER_INPUT_TERMINAL_ID, AUDIO_TERMINAL_STREAMING, 0, // AssociatedOutputTerminal
2, // TotalChannels
0x0003, // ChannelConfig
0, // ChannelStrIndex
NO_DESCRIPTOR},
// speaker_feature_unit
{ sizeof(USB_Audio_StdDescriptor_FeatureUnit_t), DTYPE_CSInterface,
AUDIO_DSUBTYPE_CSInterface_Feature,
USB_SPEAKER_FEATURE_UNIT_ID,
USB_SPEAKER_FEATURE_UNIT_SOURCE_ID, 1, // bControlSize
{ 0x03, 0x00, 0x00}, // bmaControls
NO_DESCRIPTOR},
// speaker_output_terminal
{ { sizeof(USB_Audio_Descriptor_OutputTerminal_t), DTYPE_CSInterface},
AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
USB_SPEAKER_OUTPUT_TERMINAL_ID, AUDIO_TERMINAL_OUT_SPEAKER, 0, // AssociatedOutputTerminal
USB_SPEAKER_OUTPUT_TERMINAL_SOURCE_ID, NO_DESCRIPTOR},
#endif
#if (USB_MIC_ENABLE)
// mic_input_terminal
{ { sizeof(USB_Audio_Descriptor_InputTerminal_t), DTYPE_CSInterface},
AUDIO_DSUBTYPE_CSInterface_InputTerminal,
USB_MIC_INPUT_TERMINAL_ID, AUDIO_TERMINAL_IN_MIC, 0, // AssociatedOutputTerminal
1, // TotalChannels
0x0001, // ChannelConfig
0, // ChannelStrIndex
NO_DESCRIPTOR},
// mic_feature_unit
{
{ sizeof(USB_Audio_Descriptor_FeatureUnit_Mic_t),
DTYPE_CSInterface},
AUDIO_DSUBTYPE_CSInterface_Feature, USB_MIC_FEATURE_UNIT_ID,
USB_MIC_FEATURE_UNIT_SOURCE_ID, 1, // bControlSize
{ 0x03, 0x00}, // bmaControls
NO_DESCRIPTOR},
// mic_output_terminal
{ { sizeof(USB_Audio_Descriptor_OutputTerminal_t), DTYPE_CSInterface},
AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
USB_MIC_OUTPUT_TERMINAL_ID, AUDIO_TERMINAL_STREAMING, 0, // AssociatedOutputTerminal
USB_MIC_OUTPUT_TERMINAL_SOURCE_ID, NO_DESCRIPTOR},
#endif
#if (USB_SPEAKER_ENABLE)
// speaker_setting0
{ { sizeof(USB_Descriptor_Interface_t), DTYPE_Interface},
USB_INTF_SPEAKER,
0, // AlternateSetting
0, // bNumEndpoints
AUDIO_CSCP_AudioClass, AUDIO_CSCP_AudioStreamingSubclass,
AUDIO_CSCP_StreamingProtocol, NO_DESCRIPTOR},
// speaker_setting1
{ { sizeof(USB_Descriptor_Interface_t), DTYPE_Interface},
USB_INTF_SPEAKER,
1, // AlternateSetting
1, // bNumEndpoints
AUDIO_CSCP_AudioClass, AUDIO_CSCP_AudioStreamingSubclass,
AUDIO_CSCP_StreamingProtocol, NO_DESCRIPTOR},
// speaker_audio_stream
{ { sizeof(USB_Audio_Descriptor_Interface_AS_t), DTYPE_CSInterface},
AUDIO_DSUBTYPE_CSInterface_General, 1, // TerminalLink #1 USB Streaming IT
1, // FrameDelay
{ USB_AUDIO_FORMAT_PCM & 0xff, (USB_AUDIO_FORMAT_PCM >> 8)
& 0xff}},
// speaker_audio_format
{ { sizeof(USB_Audio_Descriptor_Format_t)
+ sizeof(USB_Audio_SampleFreq_t), DTYPE_CSInterface},
AUDIO_DSUBTYPE_CSInterface_FormatType, USB_AUDIO_FORMAT_PCM, 2, // Channels
2, // SubFrameSize
0x10, // BitsResolution
1 // TotalDiscreteSampleRates
},
// speaker_sample_rate AUDIO_SAMPLE_FREQ
{ 0x80, 0xbb, 0x00},
// speaker_stream_endpoint
{ {
{ sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), DTYPE_Endpoint},
USB_EDP_SPEAKER,
EP_TYPE_ISOCHRONOUS | (EP_SYNC_TYPE_ADAPTIVE << 2) | (EP_USAGE_TYPE_DATA << 4), // Attributes ENDPOINT_ATTR_ASYNC
0x00c0, // EndpointSize USB_MIC_CHANNELS_LEN
1 // PollingIntervalMS
}, 0, // Refresh
0 // SyncEndpointNumber
},
// speaker_stream_endpoint_spc
{
{ sizeof(USB_Audio_Descriptor_StreamEndpoint_Spc_t),
DTYPE_CSEndpoint}, AUDIO_DSUBTYPE_CSInterface_General,
AUDIO_EP_FULL_PACKETS_ONLY | AUDIO_EP_SAMPLE_FREQ_CONTROL, 0, // LockDelayUnits
{ 0, 0} // LockDelay
},
#if(USB_AUDIO_441K_ENABLE)
NOTE("Add 441k descriptor if USB_AUDIO_441K_ENABLE defined")
#endif
#endif
#if (USB_MIC_ENABLE)
// mic_setting0
{ { sizeof(USB_Descriptor_Interface_t), DTYPE_Interface},
USB_INTF_MIC,
0, // AlternateSetting
0, // bNumEndpoints
AUDIO_CSCP_AudioClass, AUDIO_CSCP_AudioStreamingSubclass,
AUDIO_CSCP_StreamingProtocol, NO_DESCRIPTOR
},
// mic_setting1
{ { sizeof(USB_Descriptor_Interface_t), DTYPE_Interface},
USB_INTF_MIC,
1, // AlternateSetting
1, // bNumEndpoints
AUDIO_CSCP_AudioClass, AUDIO_CSCP_AudioStreamingSubclass,
AUDIO_CSCP_StreamingProtocol, NO_DESCRIPTOR
},
// mic_audio_stream
{ { sizeof(USB_Audio_Descriptor_Interface_AS_t), DTYPE_CSInterface},
AUDIO_DSUBTYPE_CSInterface_General, 6, // TerminalLink #6USB USB Streaming OT
1, // FrameDelay
{ USB_AUDIO_FORMAT_PCM & 0xff, (USB_AUDIO_FORMAT_PCM >> 8)& 0xff}
},
// mic_audio_format
{ { sizeof(USB_Audio_Descriptor_Format_t)
+ sizeof(USB_Audio_SampleFreq_t), DTYPE_CSInterface},
AUDIO_DSUBTYPE_CSInterface_FormatType, USB_AUDIO_FORMAT_PCM, // FormatType
MIC_CHANNEL_COUNT, // Channels
2, // SubFrameSize
MIC_RESOLUTION_BIT, // BitsResolution
1 // TotalDiscreteSampleRates
},
// mic_sample_rate
{(MIC_SAMPLE_RATE & 0xff), (MIC_SAMPLE_RATE >> 8), 0x00},
// mic_stream_endpoint
{ {
{ sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), DTYPE_Endpoint}
, ENDPOINT_DIR_MASK | USB_EDP_MIC,
EP_TYPE_ISOCHRONOUS | (EP_SYNC_TYPE_SYNC << 2) | (EP_USAGE_TYPE_DATA << 4), // Attributes
USB_MIC_CHANNELS_LEN, 1 // PollingIntervalMS
},
0, // Refresh
0 // SyncEndpointNumber
},
// mic_stream_endpoint_spc
{
{ sizeof(USB_Audio_Descriptor_StreamEndpoint_Spc_t),
DTYPE_CSEndpoint}, AUDIO_DSUBTYPE_CSInterface_General,
AUDIO_EP_SAMPLE_FREQ_CONTROL, 0, // LockDelayUnits
{ 0, 0} // LockDelay
},
#endif
#if(0)
// audio_interface
{
{sizeof(USB_Descriptor_Interface_t), DTYPE_Interface},
USB_INTF_AUDIO_HID,
0, // AlternateSetting
1, // bNumEndpoints
HID_CSCP_HIDClass, HID_CSCP_NonBootSubclass,
HID_CSCP_NonBootProtocol, NO_DESCRIPTOR
},
{
// audio_hid
{
{sizeof(USB_HID_Descriptor_HID_t), HID_DTYPE_HID}, 0x0111, // HIDSpec
USB_HID_COUNTRY_NONE, 1, // TotalReportDescriptors
HID_DTYPE_Report, {sizeof(usbaud_report_desc), 0x00}, // HIDReportLength sizeof(Report)
},
// audio_in_endpoint
{
{sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint},
ENDPOINT_DIR_IN | USB_EDP_AUDIO,
EP_TYPE_INTERRUPT, 0x0010, // EndpointSize
1 // PollingIntervalMS
}
},
#endif
#if (USB_KEYBOARD_ENABLE)
// keyboardInterface
{ {sizeof(USB_Descriptor_Interface_t), DTYPE_Interface},
USB_INTF_KEYBOARD,
0, // AlternateSetting
1, // bNumEndpoints
HID_CSCP_HIDClass, HID_CSCP_BootSubclass,
HID_CSCP_KeyboardBootProtocol, NO_DESCRIPTOR
},
{
// keyboard_hid
{
{sizeof(USB_HID_Descriptor_HID_t), HID_DTYPE_HID}, 0x0111, // HIDSpec
USB_HID_COUNTRY_US, 1, // TotalReportDescriptors
HID_DTYPE_Report, {sizeof(keyboard_report_desc), 0x00}, // HIDReportLength
},
// keyboard_in_endpoint
{
{sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint},
ENDPOINT_DIR_IN | USB_EDP_KEYBOARD_IN,
EP_TYPE_INTERRUPT, 0x0008, // EndpointSize
USB_KEYBOARD_POLL_INTERVAL // PollingIntervalMS
},
},
#endif
#if (USB_MOUSE_ENABLE)
// mouse_interface
{ { sizeof(USB_Descriptor_Interface_t), DTYPE_Interface},
USB_INTF_MOUSE,
0, // AlternateSetting
1, // bNumEndpoints
HID_CSCP_HIDClass, HID_CSCP_BootSubclass,
HID_CSCP_MouseBootProtocol, NO_DESCRIPTOR}, {
// mouse_hid
{ { sizeof(USB_HID_Descriptor_HID_t), HID_DTYPE_HID}, 0x0111, // HIDSpec
USB_HID_COUNTRY_US, 1, // TotalReportDescriptors
HID_DTYPE_Report, {sizeof(mouse_report_desc), 0x00}, // HIDReportLength
},
// mouse_in_endpoint
{ { sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint},
ENDPOINT_DIR_IN | USB_EDP_MOUSE,
EP_TYPE_INTERRUPT, 0x0008, // EndpointSize
USB_MOUSE_POLL_INTERVAL // PollingIntervalMS
}},
#endif
#if (USB_SOMATIC_ENABLE)
// SOMATICInterface
{ {sizeof(USB_Descriptor_Interface_t), DTYPE_Interface},
USB_INTF_SOMATIC,
0, // AlternateSetting
1, // bNumEndpoints
HID_CSCP_HIDClass, HID_CSCP_BootSubclass,
HID_CSCP_NonBootProtocol, NO_DESCRIPTOR
},
{
// SOMATIC_hid
{
{sizeof(USB_HID_Descriptor_HID_t), HID_DTYPE_HID}, 0x0111, // HIDSpec
USB_HID_COUNTRY_US, 1, // TotalReportDescriptors
HID_DTYPE_Report, {sizeof(somatic_report_desc), 0x00}, // HIDReportLength
},
// SOMATIC_in_endpoint
{
{sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint},
ENDPOINT_DIR_IN | USB_EDP_SOMATIC_OUT,
EP_TYPE_INTERRUPT, 0x0010, // EndpointSize
USB_SOMATIC_POLL_INTERVAL // PollingIntervalMS
},
},
#endif
};
u8* usbdesc_get_language(void) {
return (u8*) (&language_desc);
}
u8* usbdesc_get_vendor(void) {
return (u8*) (&vendor_desc);
}
u8* usbdesc_get_product(void) {
return (u8*) (&product_desc);
}
#if (MS_OS_DESCRIPTOR_ENABLE)
u8* usbdesc_get_OS_descriptor(void) {
return (u8*) (&microsoft_OS_desc);
}
u8* usbdesc_get_OSFeature(int *length) {
*length = sizeof(OSFeatureDescriptor);
return (u8*) (&OSFeatureDescriptor);
}
u8* usbdesc_get_compatID(int *length) {
*length = OSFeatureDescriptor_compatID.compatID_Header.dwLength;
return (u8*) (&OSFeatureDescriptor_compatID);
}
#endif
u8* usbdesc_get_serial(void) {
return (u8*) (&serial_desc);
}
u8* usbdesc_get_device(void) {
return (u8*) (&device_desc);
}
u8* usbdesc_get_configuration(void) {
return (u8*) (&configuration_desc);
}
#if(0)
u8* usbdesc_get_audio(void) {
return (u8*) (&configuration_desc.audio_descriptor);
}
#endif
#if (USB_MOUSE_ENABLE)
u8* usbdesc_get_mouse(void) {
return (u8*) (&configuration_desc.mouse_descriptor);
}
#endif
#if (USB_KEYBOARD_ENABLE)
u8* usbdesc_get_keyboard(void) {
return (u8*) (&configuration_desc.keyboard_descriptor);
}
#endif
#if (USB_SOMATIC_ENABLE)
u8* usbdesc_get_somatic(void) {
return (u8*) (&configuration_desc.somatic_descriptor);
}
#endif
#if (USB_CDC_ENABLE)
u8* usbdesc_get_cdc(void) {
return (u8*) (&configuration_desc.cdc_descriptor);
}
u8* usbdesc_get_cdc_inf(void) {
return (u8*) (&configuration_desc.cdc_interface);
}
#endif
#if (AUDIO_HOGP)
u8* usbdesc_get_audio_hogp(void) {
return (u8*) (&configuration_desc.audio_hogp_descriptor);
}
#endif
+419
View File
@@ -0,0 +1,419 @@
/********************************************************************************************************
* @file usbdesc.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include <application/usbstd/AudioClassCommon.h>
#include <application/usbstd/CDCClassCommon.h>
#include <application/usbstd/HIDClassCommon.h>
#include <application/usbstd/PrinterClassCommon.h>
#include <application/usbstd/USBController.h>
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
// interface id
typedef enum {
#if AUDIO_HOGP
USB_INTF_AUDIO_HOGP, //Must place in this position
#endif
#if USB_CDC_ENABLE
USB_INTF_CDC_CCI,
USB_INTF_CDC_DCI,
#endif
#if (USB_PRINTER_ENABLE)
USB_INTF_PRINTER,
#endif
#if (USB_SPEAKER_ENABLE || USB_MIC_ENABLE)
USB_INTF_AUDIO_CONTROL,
#endif
#if (USB_SPEAKER_ENABLE)
USB_INTF_SPEAKER,
#endif
#if (USB_MIC_ENABLE)
USB_INTF_MIC,
#endif
#if(0)
USB_INTF_AUDIO_HID, // use for volumn control, mute, next, prev track, move to mouse hid
#endif
#if USB_KEYBOARD_ENABLE
USB_INTF_KEYBOARD,
#endif
#if USB_MOUSE_ENABLE
USB_INTF_MOUSE,
#endif
#if USB_SOMATIC_ENABLE
USB_INTF_SOMATIC,
#endif
USB_INTF_MAX,
} USB_INTF_ID_E;
enum {
USB_SPEAKER_FEATURE_UNIT = USB_SPEAKER_ENABLE,
USB_MIC_FEATURE_UNIT = USB_MIC_ENABLE,
};
enum {
USB_SPEAKER_INPUT_TERMINAL_ID = 1,
USB_SPEAKER_FEATURE_UNIT_ID,
USB_SPEAKER_OUTPUT_TERMINAL_ID,
USB_MIC_INPUT_TERMINAL_ID,
USB_MIC_FEATURE_UNIT_ID,
USB_MIC_OUTPUT_TERMINAL_ID,
};
enum {
USB_SPEAKER_FEATURE_UNIT_SOURCE_ID = 1,
USB_SPEAKER_OUTPUT_TERMINAL_SOURCE_ID,
USB_MIC_FEATURE_UNIT_SOURCE_ID = 4,
USB_MIC_OUTPUT_TERMINAL_SOURCE_ID,
};
#if(USB_MIC_ENABLE)
#define USB_MIC_CHANNELS_LEN (MIC_CHANNEL_COUNT*(MIC_SAMPLE_RATE*MIC_RESOLUTION_BIT/1000/8))
#endif
enum {
USB_AUDIO_FORMAT_UNKNOWN = 0,
USB_AUDIO_FORMAT_PCM,
USB_AUDIO_FORMAT_ADPCM,
USB_AUDIO_FORMAT_IEEE_FLOAT,
USB_AUDIO_FORMAT_IBM_CVSD,
USB_AUDIO_FORMAT_ALAW,
USB_AUDIO_FORMAT_MULAW,
USB_AUDIO_FORMAT_WMAVOICE9,
USB_AUDIO_FORMAT_OKI_ADPCM,
USB_AUDIO_FORMAT_DVI_ADPCM,
USB_AUDIO_FORMAT_IMA_ADPCM,
USB_AUDIO_FORMAT_MEDIASPACE_ADPCM,
USB_AUDIO_FORMAT_SIERRA_ADPCM,
USB_AUDIO_FORMAT_G723_ADPCM,
USB_AUDIO_FORMAT_DIGISTD,
USB_AUDIO_FORMAT_DIGIFIX,
USB_AUDIO_FORMAT_DIALOGIC_OKI_ADPCM,
USB_AUDIO_FORMAT_MEDIAVISION_ADPCM,
USB_AUDIO_FORMAT_YAMAHA_ADPCM,
USB_AUDIO_FORMAT_SONARC,
USB_AUDIO_FORMAT_DSPGROUP_TRUESPEECH,
USB_AUDIO_FORMAT_ECHOSC1,
USB_AUDIO_FORMAT_AUDIOFILE_AF36,
USB_AUDIO_FORMAT_APTX,
USB_AUDIO_FORMAT_AUDIOFILE_AF10,
USB_AUDIO_FORMAT_DOLBY_AC2,
USB_AUDIO_FORMAT_GSM610,
USB_AUDIO_FORMAT_MSNAUDIO,
USB_AUDIO_FORMAT_ANTEX_ADPCME,
USB_AUDIO_FORMAT_CONTROL_RES_VQLPC,
USB_AUDIO_FORMAT_DIGIREAL,
USB_AUDIO_FORMAT_DIGIADPCM,
USB_AUDIO_FORMAT_CONTROL_RES_CR10,
USB_AUDIO_FORMAT_NMS_VBXADPCM,
USB_AUDIO_FORMAT_CS_IMAADPCM,
USB_AUDIO_FORMAT_ECHOSC3,
USB_AUDIO_FORMAT_ROCKWELL_ADPCM,
USB_AUDIO_FORMAT_ROCKWELL_DIGITALK,
USB_AUDIO_FORMAT_XEBEC,
USB_AUDIO_FORMAT_G721_ADPCM,
USB_AUDIO_FORMAT_G728_CELP,
USB_AUDIO_FORMAT_MPEG,
USB_AUDIO_FORMAT_MPEGLAYER3,
USB_AUDIO_FORMAT_CIRRUS,
USB_AUDIO_FORMAT_ESPCM,
USB_AUDIO_FORMAT_VOXWARE,
USB_AUDIO_FORMAT_WAVEFORMAT_CANOPUS_ATRAC,
USB_AUDIO_FORMAT_G726_ADPCM,
USB_AUDIO_FORMAT_G722_ADPCM,
USB_AUDIO_FORMAT_DSAT,
USB_AUDIO_FORMAT_DSAT_DISPLAY,
USB_AUDIO_FORMAT_SOFTSOUND,
USB_AUDIO_FORMAT_RHETOREX_ADPCM,
USB_AUDIO_FORMAT_MSAUDIO1,
USB_AUDIO_FORMAT_WMAUDIO2,
USB_AUDIO_FORMAT_WMAUDIO3,
USB_AUDIO_FORMAT_WMAUDIO_LOSSLESS,
USB_AUDIO_FORMAT_CREATIVE_ADPCM,
USB_AUDIO_FORMAT_CREATIVE_FASTSPEECH8,
USB_AUDIO_FORMAT_CREATIVE_FASTSPEECH10,
USB_AUDIO_FORMAT_QUARTERDECK,
USB_AUDIO_FORMAT_FM_TOWNS_SND,
USB_AUDIO_FORMAT_BTV_DIGITAL,
USB_AUDIO_FORMAT_OLIGSM,
USB_AUDIO_FORMAT_OLIADPCM,
USB_AUDIO_FORMAT_OLICELP,
USB_AUDIO_FORMAT_OLISBC,
USB_AUDIO_FORMAT_OLIOPR,
USB_AUDIO_FORMAT_LH_CODEC,
USB_AUDIO_FORMAT_NORRIS,
};
enum {
USB_HID_COUNTRY_NONE = 0,
USB_HID_COUNTRY_ARABIC,
USB_HID_COUNTRY_BELGIAN,
USB_HID_COUNTRY_CANADA_BI,
USB_HID_COUNTRY_CANADA_FR,
USB_HID_COUNTRY_CZECH_REPUBLIC,
USB_HID_COUNTRY_DANISH,
USB_HID_COUNTRY_FINNISH,
USB_HID_COUNTRY_FRENCH,
USB_HID_COUNTRY_GERMAN,
USB_HID_COUNTRY_GREEK,
USB_HID_COUNTRY_HEBREW,
USB_HID_COUNTRY_HUNGARY,
USB_HID_COUNTRY_INTERNATIONAL_ISO,
USB_HID_COUNTRY_ITALIAN,
USB_HID_COUNTRY_JAPAN_KATAKANA,
USB_HID_COUNTRY_KOREAN,
USB_HID_COUNTRY_LATIN_AMERICAN,
USB_HID_COUNTRY_NETHERLANDS,
USB_HID_COUNTRY_NORWEGIAN,
USB_HID_COUNTRY_PERSIAN,
USB_HID_COUNTRY_POLAND,
USB_HID_COUNTRY_PORTUGUESE,
USB_HID_COUNTRY_RUSSIA,
USB_HID_COUNTRY_SLOVAKIA,
USB_HID_COUNTRY_SPANISH,
USB_HID_COUNTRY_SWEDISH,
USB_HID_COUNTRY_SWISS_FRENCH,
USB_HID_COUNTRY_SWISS_GERMAN,
USB_HID_COUNTRY_SWITZERLAND,
USB_HID_COUNTRY_TAIWAN,
USB_HID_COUNTRY_TURKISH_Q,
USB_HID_COUNTRY_UK,
USB_HID_COUNTRY_US,
USB_HID_COUNTRY_YUGOSLAVIA,
USB_HID_COUNTRY_TURKISH_F,
};
enum {
USB_STRING_LANGUAGE = 0,
USB_STRING_VENDOR,
USB_STRING_PRODUCT,
USB_STRING_SERIAL,
USB_STRING_MS_OS =0xee,
};
#if (USB_CDC_ENABLE)
/** Endpoint number of the CDC device-to-host notification IN endpoint. */
#define CDC_NOTIFICATION_EPNUM 2
/** Endpoint number of the CDC device-to-host data IN endpoint. */
#ifndef CDC_TX_EPNUM
#define CDC_TX_EPNUM 4 ///3
#endif
/** Endpoint number of the CDC host-to-device data OUT endpoint. */
#define CDC_RX_EPNUM 5///4
/** Size in bytes of the CDC device-to-host notification IN endpoint. */
#define CDC_NOTIFICATION_EPSIZE 8
/** Size in bytes of the CDC data IN and OUT endpoints. */
#define CDC_TXRX_EPSIZE 64
#endif /* USB_CDC_ENABLE */
typedef struct {
USB_HID_Descriptor_HID_t audio_hid;
USB_Descriptor_Endpoint_t audio_in_endpoint;
} USB_HID_Descriptor_HID_Audio_t;
typedef struct {
USB_HID_Descriptor_HID_t mouse_hid;
USB_Descriptor_Endpoint_t mouse_in_endpoint;
} USB_HID_Descriptor_HID_Mouse_t;
typedef struct {
USB_HID_Descriptor_HID_t keyboard_hid;
USB_Descriptor_Endpoint_t keyboard_in_endpoint;
} USB_HID_Descriptor_HID_Keyboard_t;
typedef struct {
USB_HID_Descriptor_HID_t somatic_hid;
USB_Descriptor_Endpoint_t somatic_in_endpoint;
USB_Descriptor_Endpoint_t somatic_out_endpoint;
} USB_HID_Descriptor_HID_Somatic_t;
typedef struct {
// CDC Control Interface
USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header;
USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM;
USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union;
USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_CallManagement;
USB_Descriptor_Endpoint_t CDC_NotificationEndpoint;
// CDC Data Interface
USB_Descriptor_Interface_t CDC_DCI_Interface;
USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
} USB_CDC_Descriptor_t;
typedef struct {
USB_Descriptor_Configuration_Hdr_t Config;
#if AUDIO_HOGP
USB_Descriptor_Interface_t audio_hogp_interface;
USB_HID_Descriptor_HID_Keyboard_t audio_hogp_descriptor;
#endif
#if (USB_CDC_ENABLE)
#if 0
// IAD0
USB_Descriptor_Interface_Association_t cdc_iad;
#endif
// CDC Interface
USB_Descriptor_Interface_t cdc_interface;
USB_CDC_Descriptor_t cdc_descriptor;
#endif
#if(USB_PRINTER_ENABLE)
// printer HID Interface
USB_Descriptor_Interface_t printer_interface;
USB_Descriptor_Endpoint_t printer_in_endpoint;
#if(!USB_SOMATIC_ENABLE)
USB_Descriptor_Endpoint_t printer_out_endpoint;
#endif
#endif
#if (USB_MIC_ENABLE || USB_SPEAKER_ENABLE)
USB_Descriptor_Interface_t audio_control_interface;
#if (USB_MIC_ENABLE && USB_SPEAKER_ENABLE)
USB_Audio_Descriptor_Interface_AC_TL_t audio_control_interface_ac;
#else
USB_Audio_Descriptor_Interface_AC_t audio_control_interface_ac;
#endif
#endif
#if (USB_SPEAKER_ENABLE)
USB_Audio_Descriptor_InputTerminal_t speaker_input_terminal;
USB_Audio_StdDescriptor_FeatureUnit_t speaker_feature_unit;
USB_Audio_Descriptor_OutputTerminal_t speaker_output_terminal;
#endif
#if (USB_MIC_ENABLE)
USB_Audio_Descriptor_InputTerminal_t mic_input_terminal;
USB_Audio_Descriptor_FeatureUnit_Mic_t mic_feature_unit;
USB_Audio_Descriptor_OutputTerminal_t mic_output_terminal;
#endif
#if (USB_SPEAKER_ENABLE)
USB_Descriptor_Interface_t speaker_setting0;
USB_Descriptor_Interface_t speaker_setting1;
USB_Audio_Descriptor_Interface_AS_t speaker_audio_stream;
USB_Audio_Descriptor_Format_t speaker_audio_format;
USB_Audio_SampleFreq_t speaker_sample_rate;
USB_Audio_Descriptor_StreamEndpoint_Std_t speaker_stream_endpoint;
USB_Audio_Descriptor_StreamEndpoint_Spc_t speaker_stream_endpoint_spc;
#if(USB_AUDIO_441K_ENABLE)
NOTE("Add 441k descriptor if USB_AUDIO_441K_ENABLE defined")
#endif
#endif
#if (USB_MIC_ENABLE)
USB_Descriptor_Interface_t mic_setting0;
USB_Descriptor_Interface_t mic_setting1;
USB_Audio_Descriptor_Interface_AS_t mic_audio_stream;
USB_Audio_Descriptor_Format_t mic_audio_format;
USB_Audio_SampleFreq_t mic_sample_rate;
USB_Audio_Descriptor_StreamEndpoint_Std_t mic_stream_endpoint;
USB_Audio_Descriptor_StreamEndpoint_Spc_t mic_stream_endpoint_spc;
#endif
#if (0)
// audio HID Interface
USB_Descriptor_Interface_t audio_interface;
USB_HID_Descriptor_HID_Audio_t audio_descriptor;
#endif
#if (USB_KEYBOARD_ENABLE)
// Keyboard HID Interface
USB_Descriptor_Interface_t keyboard_interface;
USB_HID_Descriptor_HID_Keyboard_t keyboard_descriptor;
#endif
#if (USB_MOUSE_ENABLE)
// Mouse HID Interface
USB_Descriptor_Interface_t mouse_interface;
USB_HID_Descriptor_HID_Mouse_t mouse_descriptor;
#endif
#if (USB_SOMATIC_ENABLE)
// SOMATIC HID Interface
USB_Descriptor_Interface_t somatic_interface;
USB_HID_Descriptor_HID_Somatic_t somatic_descriptor;
#endif
} USB_Descriptor_Configuration_t;
typedef struct {
u32 dwLength; // length, in bytes, of the complete extended compat ID descriptor
u16 bcdVersion; // BCD The descriptors version number, in binary coded decimal (BCD) format
u16 wIndex; // An index that identifies the particular OS feature descriptor
u8 bCount; //The number of custom property sections
u8 RESERVED[7]; //Reserved
}USB_MS_OS_compatID_Header_t;
typedef struct {
u8 bFirstInterfaceNumber; //The interface or function number
u8 RESERVED1; //Reserved
u8 compatibleID[8]; //The functions compatible ID
u8 subCompatibleID[8]; //The functions subcompatible ID
u8 RESERVED2[6]; //Reserved
}USB_MS_OS_compatID_Function_t;
typedef struct {
USB_MS_OS_compatID_Header_t compatID_Header;
USB_MS_OS_compatID_Function_t compatID_Function[];
}USB_MS_OS_compatID_t;
u8* usbdesc_get_language(void);
u8* usbdesc_get_vendor(void);
u8* usbdesc_get_product(void);
u8* usbdesc_get_serial(void);
u8* usbdesc_get_device(void);
u8* usbdesc_get_configuration(void);
#if(USB_MIC_ENABLE || USB_SPEAKER_ENABLE)
u8* usbdesc_get_audio(void);
#endif
#if (USB_MOUSE_ENABLE)
u8* usbdesc_get_mouse(void);
#endif
#if (USB_KEYBOARD_ENABLE)
u8* usbdesc_get_keyboard(void);
#endif
#if (USB_SOMATIC_ENABLE)
u8* usbdesc_get_somatic(void);
#endif
#if (USB_CRC_ENABLE)
u8 *usbdesc_get_cdc(void);
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
+348
View File
@@ -0,0 +1,348 @@
/********************************************************************************************************
* @file usbkeycode.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#define VK_NONE 0x00
// function key bitmap
#define VK_MSK_CTRL 0x01
#define VK_MSK_SHIFT 0x02
#define VK_MSK_ALT 0x04
#define VK_MSK_WIN 0x08
#define VK_MSK_LCTRL 0x01
#define VK_MSK_LSHIFT 0x02
#define VK_MSK_LALT 0x04
#define VK_MSK_LWIN 0x08
#define VK_MSK_RCTRL 0x10
#define VK_MSK_RSHIFT 0x20
#define VK_MSK_RALT 0x40
#define VK_MSK_RWIN 0x80
// ordinary keys
#define VK_A 0x04
#define VK_B 0x05
#define VK_C 0x06
#define VK_D 0x07
#define VK_E 0x08
#define VK_F 0x09
#define VK_G 0x0a
#define VK_H 0x0b
#define VK_I 0x0c
#define VK_J 0x0d
#define VK_K 0x0e
#define VK_L 0x0f
#define VK_M 0x10
#define VK_N 0x11
#define VK_O 0x12
#define VK_P 0x13
#define VK_Q 0x14
#define VK_R 0x15
#define VK_S 0x16
#define VK_T 0x17
#define VK_U 0x18
#define VK_V 0x19
#define VK_W 0x1a
#define VK_X 0x1b
#define VK_Y 0x1c
#define VK_Z 0x1d
#define VK_1 0x1e
#define VK_2 0x1f
#define VK_3 0x20
#define VK_4 0x21
#define VK_5 0x22
#define VK_6 0x23
#define VK_7 0x24
#define VK_8 0x25
#define VK_9 0x26
#define VK_0 0x27
#define VK_ENTER 0x28
#define VK_ESC 0x29
#define VK_BACKSPACE 0x2a
#define VK_TAB 0x2b
#define VK_SPACE 0x2c
#define VK_MINUS 0x2d
#define VK_EQUAL 0x2e
#define VK_LBRACE 0x2f
#define VK_RBRACE 0x30
#define VK_BACKSLASH 0x31
#define VK_NUMBER 0x32
#define VK_SEMICOLON 0x33
#define VK_QUOTE 0x34
#define VK_TILDE 0x35
#define VK_COMMA 0x36
#define VK_PERIOD 0x37
#define VK_SLASH 0x38
#define VK_CAPITAL 0x39
#define VK_F1 0x3a
#define VK_F2 0x3b
#define VK_F3 0x3c
#define VK_F4 0x3d
#define VK_F5 0x3e
#define VK_F6 0x3f
#define VK_F7 0x40
#define VK_F8 0x41
#define VK_F9 0x42
#define VK_F10 0x43
#define VK_F11 0x44
#define VK_F12 0x45
#define VK_PRINTSCREEN 0x46
#define VK_SCR_LOCK 0x47
#define VK_PAUSE 0x48
#define VK_INSERT 0x49
#define VK_HOME 0x4a
#define VK_PAGE_UP 0x4b
#define VK_DELETE 0x4c
#define VK_END 0x4d
#define VK_PAGE_DOWN 0x4e
#define VK_RIGHT 0x4f
#define VK_LEFT 0x50
#define VK_DOWN 0x51
#define VK_UP 0x52
#define VK_NUM_LOCK 0x53
#define VKPAD_SLASH 0x54
#define VKPAD_ASTERIX 0x55
#define VKPAD_MINUS 0x56
#define VKPAD_PLUS 0x57
#define VKPAD_ENTER 0x58
#define VKPAD_1 0x59
#define VKPAD_2 0x5a
#define VKPAD_3 0x5b
#define VKPAD_4 0x5c
#define VKPAD_5 0x5d
#define VKPAD_6 0x5e
#define VKPAD_7 0x5f
#define VKPAD_8 0x60
#define VKPAD_9 0x61
#define VKPAD_0 0x62
#define VKPAD_PERIOD 0x63
#define VK_K45 0x64
#define VK_APP 0x65
// below KEY is for ELAN's application matrix
#define VK_C9R1 0xf0 //C9R1 00
#define VK_C9R6 0xf1 //C9R6 000
#define VK_RMB 0xf2 //C7R3
#define VK_EURO 0xf3 //C0R2
#define VK_MMODE 0xf4 //C9R4
#define VK_K107 0x85 //ok
#define VK_K56 0x87 //ok
#define VK_ROMA 0x88 //ok
#define VK_K14 0x89 //ok
#define VK_CHG 0x8a //ok
#define VK_NCHG 0x8b //ok
#define VK_KCR 0x90 //ok,K151
#define VK_KCL 0x91 //ok,K150
// NOT standard, use these reserved code to distinguish ctrol keys
#ifndef CTRL_SHIFT_E0E7
#define CTRL_SHIFT_E0E7 1
#endif
#if CTRL_SHIFT_E0E7
#define VK_CTRL 0xe0
#define VK_SHIFT 0xe1
#define VK_ALT 0xe2
#define VK_WIN 0xe3
#define VK_RCTRL 0xe4
#define VK_RSHIFT 0xe5
#define VK_RALT 0xe6
#define VK_RWIN 0xe7
#else
#define VK_CTRL 0x90
#define VK_SHIFT 0x91
#define VK_ALT 0x92
#define VK_WIN 0x93
#define VK_RCTRL 0x94
#define VK_RSHIFT 0x95
#define VK_RALT 0x96
#define VK_RWIN 0x97
#endif
enum{
VK_EXT_START = 0xa0,
VK_SYS_START = VK_EXT_START, //0xa0
VK_SLEEP = VK_SYS_START, //0xa0, sleep
VK_POWER, //0xa1, power
VK_WAKEUP, //0xa2, wake-up
// VK_MCE_STR, //0xa3
// VK_MY_MUSIC, //0xa4
VK_SYS_END, //0xa3
VK_SYS_CNT = (VK_SYS_END - VK_SYS_START),//0xa3-0xa0=0x03
VK_MEDIA_START = VK_SYS_END, //0xa3
VK_W_SRCH = VK_MEDIA_START, //0xa3
VK_WEB, //0xa4
VK_W_BACK,
VK_W_FORWRD,
VK_W_STOP,
VK_W_REFRESH,
VK_W_FAV, //0xa9
VK_MEDIA,
VK_MAIL,
VK_CAL,
VK_MY_COMP,
VK_NEXT_TRK,
VK_PREV_TRK,
VK_STOP, //b0
VK_PLAY_PAUSE,
VK_W_MUTE,
VK_VOL_UP,
VK_VOL_DN,
VK_MEDIA_END,
VK_EXT_END = VK_MEDIA_END,
VK_MEDIA_CNT = (VK_MEDIA_END - VK_MEDIA_START),//0xb5-0xa3=0x12
VK_ZOOM_IN = (VK_MEDIA_END + 1),//0xb6
VK_ZOOM_OUT , //0xb7
//special key,do it later
VK_CH_UP = 0xf0,
VK_CH_DN = 0xf1,
VK_FAST_FORWARD = 0xf2,
VK_FAST_BACKWARD = 0xf3,
VK_W_SHOPPING = 0xf4,
VK_W_APP_STORE = 0xf5,
VK_MY_FAVORIT = 0xf6,
VK_MENU = 0xf7,
VK_EXIT = 0xf8,
VK_CONFIRM = 0xf9,
VK_RETURN = 0xfa,
VK_VOICE_SEARCH = 0xfb,
VK_PROGRAM = 0xfc,
VK_LOW_BATT = 0xfd,
VK_TV_PLUS = 0xfe,
VK_TV_MINUS = 0xff,
VK_IN_OUTPUT = 0xef,
VK_TV_POWER = 0xee,
VK_STB_POWER = 0xed,
};
#define VK_FN 0xff
#define VK_EXT_LEN 2
typedef struct{
u8 val[VK_EXT_LEN];
}vk_ext_t;
// mulit-byte keycode for media keys, cannot used directly in c code..for reference
#define VK_POWER_V 0x01
#define VK_SLEEP_V 0x02
#define VK_WAKEUP_V 0x04
#define VK_W_SRCH_V {0x21,0x02}
#define VK_HOME_V {0x23,0x02}
#define VK_W_BACK_V {0x24,0x02}
#define VK_W_FORWRD_V {0x25,0x02}
#define VK_W_STOP_V {0x26,0x02}
#define VK_W_REFRESH_V {0x27,0x02}
// favorite
#define VK_W_FAV_V {0x2a,0x02}
#define VK_MEDIA_V {0x83,0x01}
#define VK_MAIL_V {0x8a,0x01}
// calculator
#define VK_CAL_V {0x92,0x01}
#define VK_MY_COMP_V {0x94,0x01}
// next track -- 01(mosue-ep/USB_EDP_MOUSE) 05(len) 03(kb-report-id/USB_HID_KB_MEDIA)
// b5(val) 00 00 00
#define VK_MENU_V {0x40,0x00}
#define VK_MENU_PICK_V {0x41,0x00}
#define VK_MENU_UP_V {0x42,0x00}
#define VK_MENU_DN_V {0x43,0x00}
#define VK_MENU_LEFT_V {0x44,0x00}
#define VK_MENU_RIGHT_V {0x45,0x00}
#define VK_CHN_UP_V {0x9c,0x00}
#define VK_CHN_DN_V {0x9d,0x00}
#define VK_PLAY_V {0xb0,0x00}
#define VK_PAUSE_V {0xb1,0x00}
#define VK_RECORD_V {0xb2,0x00}
#define VK_FAST_FORWARD_V {0xb3,0x00}
#define VK_REWIND_V {0xb4,0x00}
#define VK_NEXT_TRK_V {0xb5,0x00}
#define VK_PREV_TRK_V {0xb6,0x00}
#define VK_STOP_V {0xb7,0x00}
#define VK_PLAY_PAUSE_V {0xcd,0x00}
#define VK_W_MUTE_V {0xe2,0x00}
#define VK_VOL_UP_V {0xe9,0x00}
#define VK_VOL_DN_V {0xea,0x00}
// media key, consumer key
//reference: <<HID Usage Tables>> Consumer Page(0x0C)
typedef enum {
MKEY_POWER = 0x0030,
MKEY_RESET = 0x0031,
MKEY_SLEEP = 0x0032,
MKEY_MENU = 0x0040,
MKEY_MENU_PICK = 0x0041,
MKEY_MENU_UP = 0x0042,
MKEY_MENU_DN = 0x0043,
MKEY_MENU_LEFT = 0x0044,
MKEY_MENU_RIGHT = 0x0045,
MKEY_CHN_UP = 0x009c,
MKEY_CHN_DN = 0x009d,
MKEY_PLAY = 0x00b0,
MKEY_PAUSE = 0x00b1,
MKEY_RECORD = 0x00b2,
MKEY_FAST_FORWARD = 0x00b3,
MKEY_REWIND = 0x00b4,
MKEY_NEXT_TRK = 0x00b5,
MKEY_PREV_TRK = 0x00b6,
MKEY_STOP = 0x00b7,
MKEY_EJECT = 0x00b8,
MKEY_PLAY_PAUSE = 0x00cd,
MKEY_PLAY_SKIP = 0x00ce,
MKEY_VOLUME = 0x00e0,
MKEY_BALANCE = 0x00e1,
MKEY_MUTE = 0x00e2,
MKEY_VOL_UP = 0x00e9,
MKEY_VOL_DN = 0x00ea,
MKEY_AC_SEARCH = 0x0221,
MKEY_AC_GOTO = 0x0222,
MKEY_AC_HOME = 0x0223,
MKEY_AC_BACK = 0x0224,
MKEY_AC_FORWARD = 0x0225,
MKEY_AC_STOP = 0x0226,
MKEY_AC_REFRESH = 0x0227,
MKEY_AC_BOOKMARK = 0x022a,
MKEY_AC_HISTORY = 0x022b,
MKEY_AC_ZOOM_IN = 0x022d,
MKEY_AC_ZOOM_OUT = 0x022e,
MKEY_AC_ZOOM = 0x022f,
} media_key_t;
+100
View File
@@ -0,0 +1,100 @@
/********************************************************************************************************
* @file boot.link
*
* @brief This is the link file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
ENTRY(_RESET_ENTRY)
SECTIONS
{
NDS_SAG_LMA_FLASH = 0x20000000 ;
. = 0x20000000;
PROVIDE (BIN_BEGIN = .);
.vectors : { KEEP(*(.vectors )) }
. = 0x00000000;
.retention_reset : AT( ALIGN(LOADADDR (.vectors) + SIZEOF (.vectors),8))
{ KEEP(*(.retention_reset )) }
PROVIDE (_RETENTION_RESET_VMA_START = ADDR(.retention_reset));
PROVIDE (_RETENTION_RESET_LMA_START = LOADADDR(.retention_reset));
PROVIDE (_RETENTION_RESET_VMA_END = .);
/* By default,the aes_data section can only be used in the first 64K of IRAM, */
/* please do not change the position of this section,unless you know the correct way to use */
. = ALIGN(8);
PROVIDE (_AES_VMA_START = .);
.aes_data (NOLOAD) : { KEEP(*(.aes_data )) }
PROVIDE (_AES_VMA_END = .);
. = ALIGN(8);
.retention_data : AT( ALIGN(LOADADDR (.retention_reset) + SIZEOF (.retention_reset),8))
{ KEEP(*(.retention_data )) }
PROVIDE (_RETENTION_DATA_VMA_START = ADDR(.retention_data));
PROVIDE (_RETENTION_DATA_LMA_START = LOADADDR(.retention_data));
PROVIDE (_RETENTION_DATA_VMA_END = .);
. = ALIGN(8);
.ram_code : AT( ALIGN(LOADADDR (.retention_data) + SIZEOF (.retention_data),8))
{ KEEP(*(.ram_code )) }
PROVIDE (_RAMCODE_VMA_END = .);
PROVIDE (_RAMCODE_VMA_START = ADDR(.ram_code));
PROVIDE (_RAMCODE_LMA_START = LOADADDR(.ram_code));
PROVIDE (_RAMCODE_SIZE = SIZEOF (.ram_code));
. = ALIGN(LOADADDR (.ram_code) + SIZEOF (.ram_code), 8);
.text : AT(ALIGN(LOADADDR (.ram_code) + SIZEOF (.ram_code), 8))
{ *(.text .stub .text.* .gnu.linkonce.t.* ) KEEP(*(.text.*personality* )) *(.gnu.warning ) }
.rodata : AT(ALIGN(LOADADDR (.text) + SIZEOF (.text), ALIGNOF(.rodata)))
{ *(.rodata .rodata.* .gnu.linkonce.r.* )
*(.srodata.cst16 ) *(.srodata.cst8 ) *(.srodata.cst4 ) *(.srodata.cst2 ) *(.srodata .srodata.* )
*(.sdata2 .sdata2.* .gnu.linkonce.s.* )
}
.eh_frame_hdr : AT(ALIGN(LOADADDR (.rodata) + SIZEOF (.rodata), ALIGNOF(.eh_frame_hdr)))
{ *(.eh_frame_hdr ) }
. = ALIGN(0x20);
.eh_frame : AT(ALIGN(LOADADDR (.eh_frame_hdr) + SIZEOF (.eh_frame_hdr), 32))
{ KEEP(*(.eh_frame )) }
.exec.itable : AT(ALIGN(LOADADDR (.eh_frame) + SIZEOF (.eh_frame), ALIGNOF(.exec.itable)))
{ KEEP(*(.exec.itable)) }
. = 0x00080000;
PROVIDE( __global_pointer$ = . + (4K / 2) );
.data : AT(ALIGN(LOADADDR (.exec.itable) + SIZEOF (.exec.itable), ALIGNOF(.data)))
{ *(.data .data.* .gnu.linkonce.d.* ) KEEP(*(.gnu.linkonce.d.*personality* )) SORT(CONSTRUCTORS)
*(.sdata .sdata.* .gnu.linkonce.s.* )
}
PROVIDE (_DATA_VMA_END = .);
PROVIDE (_DATA_VMA_START = ADDR(.data));
PROVIDE (_DATA_LMA_START = LOADADDR(.data));
PROVIDE (BIN_SIZE = LOADADDR(.data) + SIZEOF(.data) - BIN_BEGIN);
. = ALIGN(8);
PROVIDE (_BSS_VMA_START = .);
.sbss (NOLOAD) : { *(.dynsbss ) *(.sbss .sbss.* .gnu.linkonce.sb.* ) *(.scommon .scommon.* ) }
.bss (NOLOAD) : { *(.dynbss ) *(.bss .bss.* .gnu.linkonce.b.* ) *(COMMON ) . = ALIGN(8); }
PROVIDE (_BSS_VMA_END = .);
. = ALIGN(8);
/* end is the starting address of the heap, the heap grows upward */
_end = .;
PROVIDE (end = .);
PROVIDE (_STACK_TOP = 0x00a0000);/*Need to prevent stack overflow*/
PROVIDE (FLASH_SIZE = 0x0100000);
}
ASSERT((BIN_SIZE)<= FLASH_SIZE, "BIN FILE OVERFLOW");
+107
View File
@@ -0,0 +1,107 @@
/********************************************************************************************************
* @file boot_DLM.link
*
* @brief This is the link file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
ENTRY(_RESET_ENTRY)
SECTIONS
{
NDS_SAG_LMA_FLASH = 0x20000000 ;
. = 0x20000000;
PROVIDE (BIN_BEGIN = .);
.vectors : { KEEP(*(.vectors )) }
. = 0x00000000;
.retention_reset : AT( ALIGN(LOADADDR (.vectors) + SIZEOF (.vectors),8))
{ KEEP(*(.retention_reset )) }
PROVIDE (_RETENTION_RESET_VMA_START = ADDR(.retention_reset));
PROVIDE (_RETENTION_RESET_LMA_START = LOADADDR(.retention_reset));
PROVIDE (_RETENTION_RESET_VMA_END = .);
/* By default,the aes_data section can only be used in the first 64K of IRAM, */
/* please do not change the position of this section,unless you know the correct way to use */
. = ALIGN(8);
PROVIDE (_AES_VMA_START = .);
.aes_data (NOLOAD) : { KEEP(*(.aes_data )) }
PROVIDE (_AES_VMA_END = .);
. = ALIGN(8);
.retention_data : AT( ALIGN(LOADADDR (.retention_reset) + SIZEOF (.retention_reset),8))
{ KEEP(*(.retention_data )) }
PROVIDE (_RETENTION_DATA_VMA_START = ADDR(.retention_data));
PROVIDE (_RETENTION_DATA_LMA_START = LOADADDR(.retention_data));
PROVIDE (_RETENTION_DATA_VMA_END = .);
. = ALIGN(8);
.ram_code : AT( ALIGN(LOADADDR (.retention_data) + SIZEOF (.retention_data),8))
{ KEEP(*(.ram_code )) }
PROVIDE (_RAMCODE_VMA_END = .);
PROVIDE (_RAMCODE_VMA_START = ADDR(.ram_code));
PROVIDE (_RAMCODE_LMA_START = LOADADDR(.ram_code));
PROVIDE (_RAMCODE_SIZE = SIZEOF (.ram_code));
. = ALIGN(LOADADDR (.ram_code) + SIZEOF (.ram_code), 8);
.text : AT(ALIGN(LOADADDR (.ram_code) + SIZEOF (.ram_code), 8))
{ *(.text .stub .text.* .gnu.linkonce.t.* ) KEEP(*(.text.*personality* )) *(.gnu.warning ) }
.rodata : AT(ALIGN(LOADADDR (.text) + SIZEOF (.text), ALIGNOF(.rodata)))
{ *(.rodata .rodata.* .gnu.linkonce.r.* )
*(.srodata.cst16 ) *(.srodata.cst8 ) *(.srodata.cst4 ) *(.srodata.cst2 ) *(.srodata .srodata.* )
*(.sdata2 .sdata2.* .gnu.linkonce.s.* )
}
.eh_frame_hdr : AT(ALIGN(LOADADDR (.rodata) + SIZEOF (.rodata), ALIGNOF(.eh_frame_hdr)))
{ *(.eh_frame_hdr ) }
. = ALIGN(0x20);
.eh_frame : AT(ALIGN(LOADADDR (.eh_frame_hdr) + SIZEOF (.eh_frame_hdr), 32))
{ KEEP(*(.eh_frame )) }
.exec.itable : AT(ALIGN(LOADADDR (.eh_frame) + SIZEOF (.eh_frame), ALIGNOF(.exec.itable)))
{ KEEP(*(.exec.itable)) }
. = 0x00080000;
.dlm_data : AT(ALIGN(LOADADDR (.exec.itable) + SIZEOF (.exec.itable), 8))
{ KEEP(*(.dlm_data )) }
PROVIDE (_DLM_DATA_VMA_START = ADDR(.dlm_data));
PROVIDE (_DLM_DATA_LMA_START = LOADADDR(.dlm_data));
PROVIDE (_DLM_DATA_VMA_END = .);
PROVIDE (BIN_SIZE = LOADADDR(.dlm_data) + SIZEOF(.dlm_data) - BIN_BEGIN);
. = 0x0001c000;
PROVIDE( __global_pointer$ = . + (4K / 2) );
.data : AT(ALIGN(LOADADDR (.dlm_data) + SIZEOF (.dlm_data), ALIGNOF(.data)))
{ *(.data .data.* .gnu.linkonce.d.* ) KEEP(*(.gnu.linkonce.d.*personality* )) SORT(CONSTRUCTORS)
*(.sdata .sdata.* .gnu.linkonce.s.* )
}
PROVIDE (_DATA_VMA_END = .);
PROVIDE (_DATA_VMA_START = ADDR(.data));
PROVIDE (_DATA_LMA_START = LOADADDR(.data));
. = ALIGN(8);
PROVIDE (_BSS_VMA_START = .);
.sbss (NOLOAD) : { *(.dynsbss ) *(.sbss .sbss.* .gnu.linkonce.sb.* ) *(.scommon .scommon.* ) }
.bss (NOLOAD) : { *(.dynbss ) *(.bss .bss.* .gnu.linkonce.b.* ) *(COMMON ) . = ALIGN(8); }
PROVIDE (_BSS_VMA_END = .);
. = ALIGN(8);
/* end is the starting address of the heap, the heap grows upward */
_end = .;
PROVIDE (end = .);
PROVIDE (_STACK_TOP = 0x0020000);/*Need to prevent stack overflow*/
PROVIDE (FLASH_SIZE = 0x0100000);
}
ASSERT((BIN_SIZE)<= FLASH_SIZE, "BIN FILE OVERFLOW");
+100
View File
@@ -0,0 +1,100 @@
/********************************************************************************************************
* @file boot_general.link
*
* @brief This is the link file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
ENTRY(_RESET_ENTRY)
SECTIONS
{
NDS_SAG_LMA_FLASH = 0x20000000 ;
. = 0x20000000;
PROVIDE (BIN_BEGIN = .);
.vectors : { KEEP(*(.vectors )) }
. = 0x00000000;
.retention_reset : AT( ALIGN(LOADADDR (.vectors) + SIZEOF (.vectors),8))
{ KEEP(*(.retention_reset )) }
PROVIDE (_RETENTION_RESET_VMA_START = ADDR(.retention_reset));
PROVIDE (_RETENTION_RESET_LMA_START = LOADADDR(.retention_reset));
PROVIDE (_RETENTION_RESET_VMA_END = .);
/* By default,the aes_data section can only be used in the first 64K of IRAM, */
/* please do not change the position of this section,unless you know the correct way to use */
. = ALIGN(8);
PROVIDE (_AES_VMA_START = .);
.aes_data (NOLOAD) : { KEEP(*(.aes_data )) }
PROVIDE (_AES_VMA_END = .);
. = ALIGN(8);
.retention_data : AT( ALIGN(LOADADDR (.retention_reset) + SIZEOF (.retention_reset),8))
{ KEEP(*(.retention_data )) }
PROVIDE (_RETENTION_DATA_VMA_START = ADDR(.retention_data));
PROVIDE (_RETENTION_DATA_LMA_START = LOADADDR(.retention_data));
PROVIDE (_RETENTION_DATA_VMA_END = .);
. = ALIGN(8);
.ram_code : AT( ALIGN(LOADADDR (.retention_data) + SIZEOF (.retention_data),8))
{ KEEP(*(.ram_code )) }
PROVIDE (_RAMCODE_VMA_END = .);
PROVIDE (_RAMCODE_VMA_START = ADDR(.ram_code));
PROVIDE (_RAMCODE_LMA_START = LOADADDR(.ram_code));
PROVIDE (_RAMCODE_SIZE = SIZEOF (.ram_code));
. = ALIGN(LOADADDR (.ram_code) + SIZEOF (.ram_code), 8);
.text : AT(ALIGN(LOADADDR (.ram_code) + SIZEOF (.ram_code), 8))
{ *(.text .stub .text.* .gnu.linkonce.t.* ) KEEP(*(.text.*personality* )) *(.gnu.warning ) }
.rodata : AT(ALIGN(LOADADDR (.text) + SIZEOF (.text), ALIGNOF(.rodata)))
{ *(.rodata .rodata.* .gnu.linkonce.r.* )
*(.srodata.cst16 ) *(.srodata.cst8 ) *(.srodata.cst4 ) *(.srodata.cst2 ) *(.srodata .srodata.* )
*(.sdata2 .sdata2.* .gnu.linkonce.s.* )
}
.eh_frame_hdr : AT(ALIGN(LOADADDR (.rodata) + SIZEOF (.rodata), ALIGNOF(.eh_frame_hdr)))
{ *(.eh_frame_hdr ) }
. = ALIGN(0x20);
.eh_frame : AT(ALIGN(LOADADDR (.eh_frame_hdr) + SIZEOF (.eh_frame_hdr), 32))
{ KEEP(*(.eh_frame )) }
.exec.itable : AT(ALIGN(LOADADDR (.eh_frame) + SIZEOF (.eh_frame), ALIGNOF(.exec.itable)))
{ KEEP(*(.exec.itable)) }
. = 0x00080000;
PROVIDE( __global_pointer$ = . + (4K / 2) );
.data : AT(ALIGN(LOADADDR (.exec.itable) + SIZEOF (.exec.itable), ALIGNOF(.data)))
{ *(.data .data.* .gnu.linkonce.d.* ) KEEP(*(.gnu.linkonce.d.*personality* )) SORT(CONSTRUCTORS)
*(.sdata .sdata.* .gnu.linkonce.s.* )
}
PROVIDE (_DATA_VMA_END = .);
PROVIDE (_DATA_VMA_START = ADDR(.data));
PROVIDE (_DATA_LMA_START = LOADADDR(.data));
PROVIDE (BIN_SIZE = LOADADDR(.data) + SIZEOF(.data) - BIN_BEGIN);
. = ALIGN(8);
PROVIDE (_BSS_VMA_START = .);
.sbss (NOLOAD) : { *(.dynsbss ) *(.sbss .sbss.* .gnu.linkonce.sb.* ) *(.scommon .scommon.* ) }
.bss (NOLOAD) : { *(.dynbss ) *(.bss .bss.* .gnu.linkonce.b.* ) *(COMMON ) . = ALIGN(8); }
PROVIDE (_BSS_VMA_END = .);
. = ALIGN(8);
/* end is the starting address of the heap, the heap grows upward */
_end = .;
PROVIDE (end = .);
PROVIDE (_STACK_TOP = 0x00a0000);/*Need to prevent stack overflow*/
PROVIDE (FLASH_SIZE = 0x0100000);
}
ASSERT((BIN_SIZE)<= FLASH_SIZE, "BIN FILE OVERFLOW");
+475
View File
@@ -0,0 +1,475 @@
/********************************************************************************************************
* @file cstartup_B91.S
*
* @brief This is the boot file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#if 1 /*default is open*/
.section .vectors, "ax"
//.org and linker's relaxation (-flto) cannot be used at the same time
//Pop corresponds to push. Before using .option norelax, use push to save the current .option configuration
//and then modify .option. After using norelax, use pop to restore
.option push
.option norelax
.org 0x0
.global _RESET_ENTRY
.type _RESET_ENTRY,@function
.align 2
_RESET_ENTRY:
j _START
//free the 6th ~ 7th byte to store the crc type of the bin file
.org 0x18
.word (BIN_SIZE)
.org 0x20
.word ('T'<<24 | 'L'<<16 | 'N'<<8 | 'K')
.org 0x26
//.short (0x0003) //READ: cmd:1x, addr:1x, data:1x, dummy:0
//.short (0x070B) //FREAD: cmd:1x, addr:1x, data:1x, dummy:8
.short (0x173B) //DREAD: cmd:1x, addr:1x, data:2x, dummy:8
//.short (0x53BB) //X2READ: cmd:1x, addr:2x, data:2x, dummy:4
//.short (0x276B) //QREAD: cmd:1x, addr:1x, data:4x, dummy:8
//.short (0x65EB) //X4READ: cmd:1x, addr:4x, data:4x, dummy:6
.option pop
.align 2
_START:
#if 0
// add debug, PB4 output 1
lui t0,0x80140 //0x8014030a
li t1, 0xef
li t2, 0x10
sb t1 , 0x30a(t0) //0x8014030a PB oen = 0xef
sb t2 , 0x30b(t0) //0x8014030b PB output = 0x10
#endif
/* Initialize global pointer */
.option push
.option norelax
la gp, __global_pointer$
.option pop
/* Initialize stack pointer */
la t0, _STACK_TOP
mv sp, t0
#ifdef __nds_execit
/* Initialize EXEC.IT table */
la t0, _ITB_BASE_
csrw uitb, t0
#endif
#ifdef __riscv_flen
/* Enable FPU */
li t0, 0x00006000
csrrs t0, mstatus, t0
/* Initialize FCSR */
fscsr zero
#endif
/* Initial machine trap-vector Base */
la t0, __vectors
csrw mtvec, t0
/* Enable vectored external plic interrupt */
csrsi mmisc_ctl, 2
/*
*#if (SUPPORT_PFT_ARCH)
* plic_set_feature(FLD_FEATURE_PREEMPT_PRIORITY_INT_EN | FLD_FEATURE_VECTOR_MODE_EN);//enable vectored in PLIC
* =(0xe4000000))= 0x03
*#else
* plic_set_feature(FLD_FEATURE_VECTOR_MODE_EN);//enable vectored in PLIC
* =(0xe4000000))= 0x02
*#endif
*/
/*vector mode enable bit (VECTORED) of the Feature Enable Register */
lui t0, 0xe4000
li t1, 0x03
sw t1, 0x0(t0) //(*(volatile unsigned long*)(0xe4000000))= 0x02
/* Enable I/D-Cache */
csrr t0, mcache_ctl
ori t0, t0, 1 #/I-Cache
ori t0, t0, 2 #/D-Cache
csrw mcache_ctl, t0
fence.i
/* Move retention reset from flash to sram */
_RETENTION_RESET_INIT:
la t1, _RETENTION_RESET_LMA_START
la t2, _RETENTION_RESET_VMA_START
la t3, _RETENTION_RESET_VMA_END
_RETENTION_RESET_BEGIN:
bleu t3, t2, _RETENTION_DATA_INIT
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _RETENTION_RESET_BEGIN
/* Move retention from flash to sram */
_RETENTION_DATA_INIT:
la t1, _RETENTION_DATA_LMA_START
la t2, _RETENTION_DATA_VMA_START
la t3, _RETENTION_DATA_VMA_END
_RETENTION_DATA_INIT_BEGIN:
bleu t3, t2, _RAMCODE_INIT
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _RETENTION_DATA_INIT_BEGIN
/* Move ramcode from flash to sram */
_RAMCODE_INIT:
la t1, _RAMCODE_LMA_START
la t2, _RAMCODE_VMA_START
la t3, _RAMCODE_VMA_END
_RAMCODE_INIT_BEGIN:
bleu t3, t2, _DATA_INIT
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _RAMCODE_INIT_BEGIN
/* Move Data from flash to sram */
_DATA_INIT:
la t1, _DATA_LMA_START
la t2, _DATA_VMA_START
la t3, _DATA_VMA_END
_DATA_INIT_BEGIN:
bleu t3, t2, _ZERO_BSS
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _DATA_INIT_BEGIN
/* Zero .bss section in sram */
_ZERO_BSS:
lui t0, 0
la t2, _BSS_VMA_START
la t3, _BSS_VMA_END
_ZERO_BSS_BEGIN:
bleu t3, t2, _ZERO_AES
sw t0, 0(t2)
addi t2, t2, 4
j _ZERO_BSS_BEGIN
/* Zero .aes section in sram */
_ZERO_AES:
lui t0, 0
la t2, _AES_VMA_START
la t3, _AES_VMA_END
_ZERO_AES_BEGIN:
bleu t3, t2, _FILL_STK
sw t0, 0(t2)
addi t2, t2, 4
j _ZERO_AES_BEGIN
/* Fill the remaining section in sram */
_FILL_STK:
#if 0
lui t0, 0x55555
addi t0, t0, 0x555
la t2, _BSS_VMA_END
la t3, _STACK_TOP
_FILL_STK_BEGIN:
bleu t3, t2, _MAIN_FUNC
sw t0, 0(t2)
addi t2, t2, 4
j _FILL_STK_BEGIN
#endif
/* Jump to the main function */
_MAIN_FUNC:
nop
la t0, main
jalr t0
nop
nop
nop
nop
nop
_END:
j _END
.section .retention_reset, "ax"
.option push
.option norelax
.global _IRESET_ENTRY
.type _IRESET_ENTRY,@function
.align 2
_IRESET_ENTRY:
/* Decide whether this is an NMI or cold reset */
j _ISTART
.org 0x22
_ISTART:
/* GPIO_DEBUG */
#if 0
// add debug, PE1 output 1
lui t0, 0x80140 //0x80140322
li t1, 0xfd
li t2, 0x02
sb t1 , 0x322(t0) //0x8014030a Pe oen = 0xfd
sb t2 , 0x323(t0) //0x8014030b Pe output = 0x02
#endif
#if 0
// add debug, PD0 output 1
lui t0,0x80140 //0x8014031a
li t1, 0xfe
li t2, 0x01
sb t1 , 0x31a(t0) //0x8014031a PD oen = 0xfe
sb t2 , 0x31b(t0) //0x8014031b PD output = 0x01
#endif
/* Initialize global pointer */
la gp, __global_pointer$
.option pop
/* Initialize stack pointer */
la t0, _STACK_TOP
mv sp, t0
#ifdef __nds_execit
/* Initialize EXEC.IT table */
la t0, _ITB_BASE_
csrw uitb, t0
#endif
#ifdef __riscv_flen
/* Enable FPU */
li t0, 0x00006000
csrrs t0, mstatus, t0
/* Initialize FCSR */
fscsr zero
#endif
/* Initial machine trap-vector Base */
la t0, __vectors
csrw mtvec, t0
/* Enable vectored external plic interrupt */
csrsi mmisc_ctl, 2
/*
*#if (SUPPORT_PFT_ARCH)
* plic_set_feature(FLD_FEATURE_PREEMPT_PRIORITY_INT_EN | FLD_FEATURE_VECTOR_MODE_EN);//enable vectored in PLIC
* =(0xe4000000))= 0x03
*#else
* plic_set_feature(FLD_FEATURE_VECTOR_MODE_EN);//enable vectored in PLIC
* =(0xe4000000))= 0x02
*#endif
*/
/*vector mode enable bit (VECTORED) of the Feature Enable Register */
lui t0, 0xe4000
li t1, 0x03
sw t1, 0x0(t0) //(*(volatile unsigned long*)(0xe4000000))= 0x03
/* Enable I/D-Cache */
csrr t0, mcache_ctl
ori t0, t0, 1 #/I-Cache
ori t0, t0, 2 #/D-Cache
csrw mcache_ctl, t0
fence.i
/* flash wakeup */
_WAKEUP_FLASH:
lui t0 , 0x80140
li t1 , 0xff
li t2 , 0x0
li t3 , 0xab
sb t1 , 0x329(t0) //mspi ie enable :0x140329:0x1f
sb t2 , 0x101(t0) //cs_low :0x140101:0x00
sb t3 , 0x100(t0) //wakeup_cmd :0x140100:0xab
_MSPI_WAIT:
lui t0 , 0x80140
lb t2 , 0x102(t0) //read reg_mspi_status FLD_MSPI_BUSY(bit0)
li t3 , 0x1
li t4 , 0x10
beq t3 , t2 ,_MSPI_WAIT
sb t4 , 0x101(t0) //cs_high :0x140101:0x10
#if 0
// add debug, PB4 output 1
lui t0,0x80140 //0x8014030a
li t1, 0x00
sb t1 , 0x30b(t0) //0x8014030b PB output = 0x00
#endif
/*efuse load need delay about 18us */
li t0 , 0
li t1 , 226
_WAIT_EFUSE_LOAD_FINISH:
addi t0 , t0 , 1
bgeu t1 , t0 , _WAIT_EFUSE_LOAD_FINISH
#if 0
// add debug, PB4 output 1
lui t0,0x80140 //0x8014030a
li t1, 0x10
sb t1 , 0x30b(t0) //0x8014030b PB output = 0x00
#endif
_MULTI_ADDRESS_BEGIN:
lui t0 , 0x80140
la t1 , g_pm_multi_addr
lw t2 , 0(t1)
sw t2 , 0x104(t0) //g_pm_multi_addr->0x80140104
#if 0
/* Move ramcode from flash to sram */
_IRAMCODE_INIT:
la t1, _RAMCODE_LMA_START
la t2, _RAMCODE_VMA_START
la t3, _RAMCODE_VMA_END
_IRAMCODE_INIT_BEGIN:
bleu t3, t2, _IDATA_INIT
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _IRAMCODE_INIT_BEGIN
#endif
/* Move Data from flash to sram */
_IDATA_INIT:
la t1, _DATA_LMA_START
la t2, _DATA_VMA_START
la t3, _DATA_VMA_END
_IDATA_INIT_BEGIN:
bleu t3, t2, _IZERO_BSS
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _IDATA_INIT_BEGIN
/* Zero .bss section in sram */
_IZERO_BSS:
lui t0, 0
la t2, _BSS_VMA_START
la t3, _BSS_VMA_END
_IZERO_BSS_BEGIN:
bleu t3, t2, _IZERO_AES
sw t0, 0(t2)
addi t2, t2, 4
j _IZERO_BSS_BEGIN
/* Zero .aes section in sram */
_IZERO_AES:
lui t0, 0
la t2, _AES_VMA_START
la t3, _AES_VMA_END
_IZERO_AES_BEGIN:
bleu t3, t2, _IFILL_STK
sw t0, 0(t2)
addi t2, t2, 4
j _IZERO_AES_BEGIN
/* Fill the remaining section in sram */
_IFILL_STK:
#if 0
lui t0, 0x55555
addi t0, t0, 0x555
la t2, _BSS_VMA_END
la t3, _STACK_TOP
_IFILL_STK_BEGIN:
bleu t3, t2, _IMAIN_FUNC
sw t0, 0(t2)
addi t2, t2, 4
j _IFILL_STK_BEGIN
#endif
/* Jump to the main function */
_IMAIN_FUNC:
nop
la t0, main
jalr t0
nop
nop
nop
nop
nop
_IEND:
j _IEND
.text
.global default_irq_entry
.align 2
default_irq_entry:
1: j 1b
.weak trap_handler
trap_handler:
1: j 1b
.macro INTERRUPT num
.weak entry_irq\num
.set entry_irq\num, default_irq_entry
.long entry_irq\num
.endm
#define VECTOR_NUMINTRS 63
.section .ram_code, "ax"
.global __vectors
.balign 256
__vectors:
/* Trap vector */
.long trap_entry
/* PLIC interrupt vector */
.altmacro
.set irqno, 1
.rept VECTOR_NUMINTRS/* .rept .endr */
INTERRUPT %irqno
.set irqno, irqno+1
.endr
#endif
+485
View File
@@ -0,0 +1,485 @@
/********************************************************************************************************
* @file cstartup_B91_DLM.S
*
* @brief This is the boot file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#if 0 /*default is close*/
.section .vectors, "ax"
//.org and linker's relaxation (-flto) cannot be used at the same time
//Pop corresponds to push. Before using .option norelax, use push to save the current .option configuration
//and then modify .option. After using norelax, use pop to restore
.option push
.option norelax
.org 0x0
.global _RESET_ENTRY
.type _RESET_ENTRY,@function
.align 2
_RESET_ENTRY:
j _START
//free the 6th ~ 7th byte to store the crc type of the bin file
.org 0x18
.word (BIN_SIZE)
.org 0x20
.word ('T'<<24 | 'L'<<16 | 'N'<<8 | 'K')
.org 0x26
//.short (0x0003) //READ: cmd:1x, addr:1x, data:1x, dummy:0
//.short (0x070B) //FREAD: cmd:1x, addr:1x, data:1x, dummy:8
.short (0x173B) //DREAD: cmd:1x, addr:1x, data:2x, dummy:8
//.short (0x53BB) //X2READ: cmd:1x, addr:2x, data:2x, dummy:4
//.short (0x276B) //QREAD: cmd:1x, addr:1x, data:4x, dummy:8
//.short (0x65EB) //X4READ: cmd:1x, addr:4x, data:4x, dummy:6
.option pop
.align 2
_START:
#if 0
// add debug, PB4 output 1
lui t0,0x80140 //0x8014030a
li t1, 0xef
li t2, 0x10
sb t1 , 0x30a(t0) //0x8014030a PB oen = 0xef
sb t2 , 0x30b(t0) //0x8014030b PB output = 0x10
#endif
/* Initialize global pointer */
.option push
.option norelax
la gp, __global_pointer$
.option pop
/* Initialize stack pointer */
la t0, _STACK_TOP
mv sp, t0
#ifdef __nds_execit
/* Initialize EXEC.IT table */
la t0, _ITB_BASE_
csrw uitb, t0
#endif
#ifdef __riscv_flen
/* Enable FPU */
li t0, 0x00006000
csrrs t0, mstatus, t0
/* Initialize FCSR */
fscsr zero
#endif
/* Initial machine trap-vector Base */
la t0, __vectors
csrw mtvec, t0
/* Enable vectored external plic interrupt */
csrsi mmisc_ctl, 2
/*
*#if (SUPPORT_PFT_ARCH)
* plic_set_feature(FLD_FEATURE_PREEMPT_PRIORITY_INT_EN | FLD_FEATURE_VECTOR_MODE_EN);//enable vectored in PLIC
* =(0xe4000000))= 0x03
*#else
* plic_set_feature(FLD_FEATURE_VECTOR_MODE_EN);//enable vectored in PLIC
* =(0xe4000000))= 0x02
*#endif
*/
/*vector mode enable bit (VECTORED) of the Feature Enable Register */
lui t0, 0xe4000
li t1, 0x03
sw t1, 0x0(t0) //(*(volatile unsigned long*)(0xe4000000))= 0x02
/* Enable I/D-Cache */
csrr t0, mcache_ctl
ori t0, t0, 1 #/I-Cache
ori t0, t0, 2 #/D-Cache
csrw mcache_ctl, t0
fence.i
/* Move retention reset from flash to sram */
_RETENTION_RESET_INIT:
la t1, _RETENTION_RESET_LMA_START
la t2, _RETENTION_RESET_VMA_START
la t3, _RETENTION_RESET_VMA_END
_RETENTION_RESET_BEGIN:
bleu t3, t2, _RETENTION_DATA_INIT
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _RETENTION_RESET_BEGIN
/* Move retention from flash to sram */
_RETENTION_DATA_INIT:
la t1, _RETENTION_DATA_LMA_START
la t2, _RETENTION_DATA_VMA_START
la t3, _RETENTION_DATA_VMA_END
_RETENTION_DATA_INIT_BEGIN:
bleu t3, t2, _RAMCODE_INIT
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _RETENTION_DATA_INIT_BEGIN
/* Move ramcode from flash to sram */
_RAMCODE_INIT:
la t1, _RAMCODE_LMA_START
la t2, _RAMCODE_VMA_START
la t3, _RAMCODE_VMA_END
_RAMCODE_INIT_BEGIN:
bleu t3, t2, _DATA_INIT
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _RAMCODE_INIT_BEGIN
/* Move DLM_Data from flash to sram */
_DLM_DATA_INIT:
la t1, _DLM_DATA_LMA_START
la t2, _DLM_DATA_VMA_START
la t3, _DLM_DATA_VMA_END
_DLM_DATA_INIT_BEGIN:
bleu t3, t2, _DATA_INIT
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _DLM_DATA_INIT_BEGIN
/* Move Data from flash to sram */
_DATA_INIT:
la t1, _DATA_LMA_START
la t2, _DATA_VMA_START
la t3, _DATA_VMA_END
_DATA_INIT_BEGIN:
bleu t3, t2, _ZERO_BSS
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _DATA_INIT_BEGIN
/* Zero .bss section in sram */
_ZERO_BSS:
lui t0, 0
la t2, _BSS_VMA_START
la t3, _BSS_VMA_END
_ZERO_BSS_BEGIN:
bleu t3, t2, _ZERO_AES
sw t0, 0(t2)
addi t2, t2, 4
j _ZERO_BSS_BEGIN
/* Zero .aes section in sram */
_ZERO_AES:
lui t0, 0
la t2, _AES_VMA_START
la t3, _AES_VMA_END
_ZERO_AES_BEGIN:
bleu t3, t2, _FILL_STK
sw t0, 0(t2)
addi t2, t2, 4
j _ZERO_AES_BEGIN
/* Fill the remaining section in sram */
_FILL_STK:
#if 0
lui t0, 0x55555
addi t0, t0, 0x555
la t2, _BSS_VMA_END
la t3, _STACK_TOP
_FILL_STK_BEGIN:
bleu t3, t2, _MAIN_FUNC
sw t0, 0(t2)
addi t2, t2, 4
j _FILL_STK_BEGIN
#endif
/* Jump to the main function */
_MAIN_FUNC:
nop
la t0, main
jalr t0
nop
nop
nop
nop
nop
_END:
j _END
.section .retention_reset, "ax"
.option push
.option norelax
.global _IRESET_ENTRY
.type _IRESET_ENTRY,@function
.align 2
_IRESET_ENTRY:
/* Decide whether this is an NMI or cold reset */
j _ISTART
.org 0x22
_ISTART:
#if 0
// add debug, PB4 output 1
lui t0,0x80140 //0x8014030a
li t1, 0xef
li t2, 0x10
sb t1 , 0x30a(t0) //0x8014030a PB oen = 0xef
sb t2 , 0x30b(t0) //0x8014030b PB output = 0x10
#endif
/* Initialize global pointer */
la gp, __global_pointer$
.option pop
/* Initialize stack pointer */
la t0, _STACK_TOP
mv sp, t0
#ifdef __nds_execit
/* Initialize EXEC.IT table */
la t0, _ITB_BASE_
csrw uitb, t0
#endif
#ifdef __riscv_flen
/* Enable FPU */
li t0, 0x00006000
csrrs t0, mstatus, t0
/* Initialize FCSR */
fscsr zero
#endif
/* Initial machine trap-vector Base */
la t0, __vectors
csrw mtvec, t0
/* Enable vectored external plic interrupt */
csrsi mmisc_ctl, 2
/*
*#if (SUPPORT_PFT_ARCH)
* plic_set_feature(FLD_FEATURE_PREEMPT_PRIORITY_INT_EN | FLD_FEATURE_VECTOR_MODE_EN);//enable vectored in PLIC
* =(0xe4000000))= 0x03
*#else
* plic_set_feature(FLD_FEATURE_VECTOR_MODE_EN);//enable vectored in PLIC
* =(0xe4000000))= 0x02
*#endif
*/
/*vector mode enable bit (VECTORED) of the Feature Enable Register */
lui t0, 0xe4000
li t1, 0x03
sw t1, 0x0(t0) //(*(volatile unsigned long*)(0xe4000000))= 0x03
/* Enable I/D-Cache */
csrr t0, mcache_ctl
ori t0, t0, 1 #/I-Cache
ori t0, t0, 2 #/D-Cache
csrw mcache_ctl, t0
fence.i
/* flash wakeup */
_WAKEUP_FLASH:
lui t0 , 0x80140
li t1 , 0xff
li t2 , 0x0
li t3 , 0xab
sb t1 , 0x329(t0) //mspi ie enable :0x140329:0x1f
sb t2 , 0x101(t0) //cs_low :0x140101:0x00
sb t3 , 0x100(t0) //wakeup_cmd :0x140100:0xab
_MSPI_WAIT:
lui t0 , 0x80140
lb t2 , 0x102(t0) //read reg_mspi_status FLD_MSPI_BUSY(bit0)
li t3 , 0x1
li t4 , 0x10
beq t3 , t2 ,_MSPI_WAIT
sb t4 , 0x101(t0) //cs_high :0x140101:0x10
#if 0
// add debug, PB4 output 1
lui t0,0x80140 //0x8014030a
li t1, 0x00
sb t1 , 0x30b(t0) //0x8014030b PB output = 0x00
#endif
/*efuse load need delay about 18us */
li t0 , 0
li t1 , 226
_WAIT_EFUSE_LOAD_FINISH:
addi t0 , t0 , 1
bgeu t1 , t0 , _WAIT_EFUSE_LOAD_FINISH
#if 0
// add debug, PB4 output 1
lui t0,0x80140 //0x8014030a
li t1, 0x10
sb t1 , 0x30b(t0) //0x8014030b PB output = 0x00
#endif
_MULTI_ADDRESS_BEGIN:
lui t0 , 0x80140
la t1 , tl_multi_addr
lw t2 , 0(t1)
sw t2 , 0x104(t0) //g_pm_multi_addr->0x80140104
#if 0
/* Move ramcode from flash to sram */
_IRAMCODE_INIT:
la t1, _RAMCODE_LMA_START
la t2, _RAMCODE_VMA_START
la t3, _RAMCODE_VMA_END
_IRAMCODE_INIT_BEGIN:
bleu t3, t2, _IDATA_INIT
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _IRAMCODE_INIT_BEGIN
#endif
/* Move DLM_Data from flash to sram */
_IDLM_DATA_INIT:
la t1, _DLM_DATA_LMA_START
la t2, _DLM_DATA_VMA_START
la t3, _DLM_DATA_VMA_END
_IDLM_DATA_INIT_BEGIN:
bleu t3, t2, _IDATA_INIT
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _IDLM_DATA_INIT_BEGIN
/* Move Data from flash to sram */
_IDATA_INIT:
la t1, _DATA_LMA_START
la t2, _DATA_VMA_START
la t3, _DATA_VMA_END
_IDATA_INIT_BEGIN:
bleu t3, t2, _IZERO_BSS
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _IDATA_INIT_BEGIN
/* Zero .bss section in sram */
_IZERO_BSS:
lui t0, 0
la t2, _BSS_VMA_START
la t3, _BSS_VMA_END
_IZERO_BSS_BEGIN:
bleu t3, t2, _IZERO_AES
sw t0, 0(t2)
addi t2, t2, 4
j _IZERO_BSS_BEGIN
/* Zero .aes section in sram */
_IZERO_AES:
lui t0, 0
la t2, _AES_VMA_START
la t3, _AES_VMA_END
_IZERO_AES_BEGIN:
bleu t3, t2, _IFILL_STK
sw t0, 0(t2)
addi t2, t2, 4
j _IZERO_AES_BEGIN
/* Fill the remaining section in sram */
_IFILL_STK:
#if 0
lui t0, 0x55555
addi t0, t0, 0x555
la t2, _BSS_VMA_END
la t3, _STACK_TOP
_IFILL_STK_BEGIN:
bleu t3, t2, _IMAIN_FUNC
sw t0, 0(t2)
addi t2, t2, 4
j _IFILL_STK_BEGIN
#endif
/* Jump to the main function */
_IMAIN_FUNC:
nop
la t0, main
jalr t0
nop
nop
nop
nop
nop
_IEND:
j _IEND
.text
.global default_irq_entry
.align 2
default_irq_entry:
1: j 1b
.weak trap_handler
trap_handler:
1: j 1b
.macro INTERRUPT num
.weak entry_irq\num
.set entry_irq\num, default_irq_entry
.long entry_irq\num
.endm
#define VECTOR_NUMINTRS 63
.section .ram_code, "ax"
.global __vectors
.balign 256
__vectors:
/* Trap vector */
.long trap_entry
/* PLIC interrupt vector */
.altmacro
.set irqno, 1
.rept VECTOR_NUMINTRS/* .rept .endr */
INTERRUPT %irqno
.set irqno, irqno+1
.endr
#endif
+81
View File
@@ -0,0 +1,81 @@
/********************************************************************************************************
* @file assert.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include "config/user_config.h" // for __DEBUG__
///////////////////////////////////////////////////////////////////////////////////
#if (__DEBUG__)
#define assert(expression) \
do{if(!(expression)) __assert (expression, __FILE__, __LINE__)}while(0)
#define __assert(expression, file, lineno) {printf ("%s:%u: assertion failed!\n", file, lineno);}
#else
#define assert(ignore) ((void) 0)
#endif
//////////////////// To do compiler warning //////////////////
// http://stackoverflow.com/questions/5966594/how-can-i-use-pragma-message-so-that-the-message-points-to-the-filelineno
// http://gcc.gnu.org/ml/gcc-help/2010-10/msg00196.html
// http://stackoverflow.com/questions/3030099/c-c-pragma-in-define-macro
#define _STRINGIFY(x) #x
#define STRINGIFY(x) _STRINGIFY(x)
#ifdef __GNUC__
#define COMPILE_MESSAGE(x) _Pragma (#x)
#endif
#if (__SHOW_TODO__)
#ifdef __GNUC__
#define TODO(x) COMPILE_MESSAGE(message ("--TODO-- " #x))
#else
#define TODO(x) __pragma(message("--TODO-- "_STRINGIFY(x) " ::function: " __FUNCTION__ "@"STRINGIFY(__LINE__)))
#endif
#else
#define TODO(x)
#endif
#if (__SHOW_WARN__)
#ifdef __GNUC__
#define WARN(x) COMPILE_MESSAGE(message ("--WARN-- " #x))
#else
#define WARN(x) __pragma(message("--WARN-- "_STRINGIFY(x) " ::function: " __FUNCTION__ "@"STRINGIFY(__LINE__)))
#endif
#else
#define WARN(x)
#endif
#if (__SHOW_WARN__)
#ifdef __GNUC__
#define NOTE(x) COMPILE_MESSAGE(message ("--NOTE-- " #x))
#else
#define NOTE(x) __pragma(message("--NOTE-- "_STRINGIFY(x) " ::function: " __FUNCTION__ "@"STRINGIFY(__LINE__)))
#endif
#else
#define NOTE(x)
#endif
+241
View File
@@ -0,0 +1,241 @@
/********************************************************************************************************
* @file bit.h
*
* @brief This is the header file for BLE SDK
*
* @author BLE GROUP
* @date 2020.06
*
* @par Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#pragma once
#include "macro_trick.h"
#define BIT(n) ( 1<<(n) )
// BITSx are internal used macro, please use BITS instead
#define BITS1(a) BIT(a)
#define BITS2(a, b) (BIT(a) | BIT(b))
#define BITS3(a, b, c) (BIT(a) | BIT(b) | BIT(c))
#define BITS4(a, b, c, d) (BIT(a) | BIT(b) | BIT(c) | BIT(d))
#define BITS5(a, b, c, d, e) (BIT(a) | BIT(b) | BIT(c) | BIT(d) | BIT(e))
#define BITS6(a, b, c, d, e, f) (BIT(a) | BIT(b) | BIT(c) | BIT(d) | BIT(e) | BIT(f))
#define BITS7(a, b, c, d, e, f, g) (BIT(a) | BIT(b) | BIT(c) | BIT(d) | BIT(e) | BIT(f) | BIT(g))
#define BITS8(a, b, c, d, e, f, g, h) (BIT(a) | BIT(b) | BIT(c) | BIT(d) | BIT(e) | BIT(f) | BIT(g) | BIT(h))
#define BITS(...) VARARG(BITS, __VA_ARGS__)
// bits range: BITS_RNG(4, 5) 0b000111110000, start from 4, length = 5
#define BIT_RNG(s, e) (BIT_MASK_LEN((e)-(s)+1) << (s))
#define BM_MASK_V(x, mask) ( (x) | (mask) )
#define BM_CLR_MASK_V(x, mask) ( (x) & ~(mask) )
#define BM_SET(x, mask) ( (x) |= (mask) )
#define BM_CLR(x, mask) ( (x) &= ~(mask) )
#define BM_IS_SET(x, mask) ( (x) & (mask) )
#define BM_IS_CLR(x, mask) ( (~x) & (mask) )
#define BM_FLIP(x, mask) ( (x) ^= (mask) )
// !!!! v is already a masked value, no need to shift
#define BM_MASK_VAL(x, mask, v) ( ((x) & ~(mask)) | (v))
#define BM_SET_MASK_VAL(x, mask, v) ( (x) = BM_MASK_VAL(x, mask, v) )
#define BIT_SET(x, n) ((x) |= BIT(n))
#define BIT_CLR(x, n) ((x) &= ~ BIT(n))
#define BIT_IS_SET(x, n) ((x) & BIT(n))
#define BIT_FLIP(x, n) ((x) ^= BIT(n))
#define BIT_SET_HIGH(x) ((x) |= BIT((sizeof((x))*8-1))) // set the highest bit
#define BIT_CLR_HIGH(x) ((x) &= ~ BIT((sizeof((x))*8-1))) // clr the highest bit
#define BIT_IS_SET_HIGH(x) ((x) & BIT((sizeof((x))*8-1))) // check the higest bit
#define BIT_MASK_LEN(len) (BIT(len)-1)
#define BIT_MASK(start, len) (BIT_MASK_LEN(len) << (start) )
//! Prepare a bitmask for insertion or combining.
#define BIT_PREP(x, start, len) ((x) & BIT_MASK(start, len))
//! Extract a bitfield of length \a len starting at bit \a start from \a y.
#define BIT_GET(x, start, len) (((x) >> (start)) & BIT_MASK_LEN(len))
#define BIT_GET_LOW(x, len) ((x) & BIT_MASK_LEN(len))
//! Insert a new bitfield value \a x into \a y.
#define BIT_MERGE(y, x, start, len) \
( y = ((y) &~ BIT_MASK(start, len)) | BIT_PREP(x, start, len) )
#define BIT_IS_EVEN(x) (((x)&1)==0)
#define BIT_IS_ODD(x) (!BIT_IS_EVEN((x)))
#define BIT_IS_POW2(x) (!((x) & ((x)-1)))
#define BIT_TURNOFF_1(x) ((x) &= ((x)-1))
#define BIT_ISOLATE_1(x) ((x) &= (-(x)))
#define BIT_PROPAGATE_1(x) ((x) |= ((x)-1))
#define BIT_ISOLATE_0(x) ((x) = ~(x) & ((x)+1))
#define BIT_TURNON_0(x) ((x) |= ((x)+1))
#define CLAMP_TO_ONE(x) (!!(x)) // compiler defined, not stardard. 0 --> 0, 1 --> 0xffffffff
#define ONES(x) BIT_MASK_LEN(x)
#define ONES_32 0xffffffff
#define ALL_SET 0xffffffff
// Return the bit index of the lowest 1 in y. ex: 0b00110111000 --> 3
#define BIT_LOW_BIT(y) (((y) & BIT(0))?0:(((y) & BIT(1))?1:(((y) & BIT(2))?2:(((y) & BIT(3))?3: \
(((y) & BIT(4))?4:(((y) & BIT(5))?5:(((y) & BIT(6))?6:(((y) & BIT(7))?7: \
(((y) & BIT(8))?8:(((y) & BIT(9))?9:(((y) & BIT(10))?10:(((y) & BIT(11))?11: \
(((y) & BIT(12))?12:(((y) & BIT(13))?13:(((y) & BIT(14))?14:(((y) & BIT(15))?15: \
(((y) & BIT(16))?16:(((y) & BIT(17))?17:(((y) & BIT(18))?18:(((y) & BIT(19))?19: \
(((y) & BIT(20))?20:(((y) & BIT(21))?21:(((y) & BIT(22))?22:(((y) & BIT(23))?23: \
(((y) & BIT(24))?24:(((y) & BIT(25))?25:(((y) & BIT(26))?26:(((y) & BIT(27))?27: \
(((y) & BIT(28))?28:(((y) & BIT(29))?29:(((y) & BIT(30))?30:(((y) & BIT(31))?31:32 \
))))))))))))))))))))))))))))))))
// Return the bit index of the highest 1 in (y). ex: 0b00110111000 --> 8
#define BIT_HIGH_BIT(y) (((y) & BIT(31))?31:(((y) & BIT(30))?30:(((y) & BIT(29))?29:(((y) & BIT(28))?28: \
(((y) & BIT(27))?27:(((y) & BIT(26))?26:(((y) & BIT(25))?25:(((y) & BIT(24))?24: \
(((y) & BIT(23))?23:(((y) & BIT(22))?22:(((y) & BIT(21))?21:(((y) & BIT(20))?20: \
(((y) & BIT(19))?19:(((y) & BIT(18))?18:(((y) & BIT(17))?17:(((y) & BIT(16))?16: \
(((y) & BIT(15))?15:(((y) & BIT(14))?14:(((y) & BIT(13))?13:(((y) & BIT(12))?12: \
(((y) & BIT(11))?11:(((y) & BIT(10))?10:(((y) & BIT(9))?9:(((y) & BIT(8))?8: \
(((y) & BIT(7))?7:(((y) & BIT(6))?6:(((y) & BIT(5))?5:(((y) & BIT(4))?4: \
(((y) & BIT(3))?3:(((y) & BIT(2))?2:(((y) & BIT(1))?1:(((y) & BIT(0))?0:32 \
))))))))))))))))))))))))))))))))
#define BM_MASK_FLD(x, mask) (((x) & (mask)) >> BIT_LOW_BIT(mask))
#define BM_SET_MASK_FLD(x, mask, v) ( (x) = BM_MASK_VAL(x,mask,v) )
//////////////////////
#define MV(m, v) (((v) << BIT_LOW_BIT(m)) & (m))
// warning MASK_VALn are internal used macro, please use MASK_VAL instead
#define MASK_VAL2(m, v) (MV(m,v))
#define MASK_VAL4(m1,v1,m2,v2) (MV(m1,v1)|MV(m2,v2))
#define MASK_VAL6(m1,v1,m2,v2,m3,v3) (MV(m1,v1)|MV(m2,v2)|MV(m3,v3))
#define MASK_VAL8(m1,v1,m2,v2,m3,v3,m4,v4) (MV(m1,v1)|MV(m2,v2)|MV(m3,v3)|MV(m4,v4))
#define MASK_VAL10(m1,v1,m2,v2,m3,v3,m4,v4,m5,v5) (MV(m1,v1)|MV(m2,v2)|MV(m3,v3)|MV(m4,v4)|MV(m5,v5))
#define MASK_VAL12(m1,v1,m2,v2,m3,v3,m4,v4,m5,v5,m6,v6) (MV(m1,v1)|MV(m2,v2)|MV(m3,v3)|MV(m4,v4)|MV(m5,v5)|MV(m6,v6))
#define MASK_VAL14(m1,v1,m2,v2,m3,v3,m4,v4,m5,v5,m6,v6,m7,v7) (MV(m1,v1)|MV(m2,v2)|MV(m3,v3)|MV(m4,v4)|MV(m5,v5)|MV(m6,v6)|MV(m7,v7))
#define MASK_VAL16(m1,v1,m2,v2,m3,v3,m4,v4,m5,v5,m6,v6,m7,v7,m8,v8) (MV(m1,v1)|MV(m2,v2)|MV(m3,v3)|MV(m4,v4)|MV(m5,v5)|MV(m6,v6)|MV(m7,v7)|MV(m8,v8))
#define MASK_VAL(...) VARARG(MASK_VAL, __VA_ARGS__)
#define FLD_MASK_VAL(x, mask, v) BM_MASK_VAL(x, mask, MV(mask,v))
#define SET_FLD(x, mask) BM_SET(x, mask)
#define CLR_FLD(x, mask) BM_CLR(x, mask)
#define FLIP_FLD(x, mask) BM_FLIP(x, mask)
#define GET_FLD(x, mask) BM_MASK_FLD(x, mask)
#define SET_FLD_V(...) VARARG(SET_FLD_V, __VA_ARGS__)
#define SET_FLD_FULL_V3(x, m, v) ((x) = MASK_VAL2(m,v))
#define SET_FLD_FULL_V5(x, m1, v1, m2, v2) ((x) = MASK_VAL4(m1,v1,m2,v2))
#define SET_FLD_FULL_V7(x, m1, v1, m2, v2, m3, v3) ((x) = MASK_VAL6(m1,v1,m2,v2,m3,v3))
#define SET_FLD_FULL_V9(x, m1, v1, m2, v2, m3, v3, m4, v4) ((x) = MASK_VAL8(m1,v1,m2,v2,m3,v3,m4,v4))
#define SET_FLD_FULL_V11(x, m1, v1, m2, v2, m3, v3, m4, v4, m5, v5) ((x) = MASK_VAL10(m1,v1,m2,v2,m3,v3,m4,v4,m5,v5))
#define SET_FLD_FULL_V13(x, m1, v1, m2, v2, m3, v3, m4, v4, m5, v5, m6, v6) ((x) = MASK_VAL12(m1,v1,m2,v2,m3,v3,m4,v4,m5,v5,m6,v6))
#define SET_FLD_FULL_V(...) VARARG(SET_FLD_FULL_V, __VA_ARGS__)
////////////////////////////////////////////////////////////////////////
#define BIT8_IFY(y) ( \
((y&0x0000000FLU)?1:0) + ((y&0x000000F0LU)? 2:0) + ((y&0x00000F00LU)? 4:0) + \
((y&0x0000F000LU)?8:0) + ((y&0x000F0000LU)?16:0) + ((y&0x00F00000LU)?32:0) + \
((y&0x0F000000LU)?64:0) + ((y&0xF0000000LU)?128:0) \
)
#define HEX_X(i) (0x##i##LU)
#define BIT_8(j) ((unsigned char)BIT8_IFY(HEX_X(j)))
#ifndef WIN32
// warning SET_FLD_Vn are internal used macro, please use SET_FLD_V instead
#define SET_FLD_V3(x, m, v) \
BM_SET_MASK_FLD(x,m,MV(m,v))
#define SET_FLD_V5(x, m1, v1, m2, v2) \
BM_SET_MASK_FLD(x, m1|m2, MV(m1,v1)| MV(m2,v2))
#define SET_FLD_V7(x, m1, v1, m2, v2, m3, v3) \
BM_SET_MASK_FLD(x, m1|m2|m3, MV(m1,v1)| MV(m2,v2)| MV(m3,v3))
#define SET_FLD_V9(x, m1, v1, m2, v2, m3, v3, m4, v4) \
BM_SET_MASK_FLD(x, m1|m2|m3|m4, MV(m1,v1)| MV(m2,v2)| MV(m3,v3)| MV(m4,v4))
#define SET_FLD_V11(x, m1, v1, m2, v2, m3, v3, m4, v4, m5, v5) \
BM_SET_MASK_FLD(x, m1|m2|m3|m4|m5, MV(m1,v1)| MV(m2,v2)| MV(m3,v3)| MV(m4,v4)| MV(m5,v5))
#define SET_FLD_V13(x, m1, v1, m2, v2, m3, v3, m4, v4, m5, v5, m6, v6) \
BM_SET_MASK_FLD(x, m1|m2|m3|m4|m5|m6, MV(m1,v1)| MV(m2,v2)| MV(m3,v3)| MV(m4,v4)| MV(m5,v5)| MV(m6,v6))
#else
#define SET_FLD_V3(x, m, v) \
__pragma(warning(push)) \
__pragma(warning(disable:4244)) \
BM_SET_MASK_FLD(x,m,MV(m,v)) \
__pragma(warning(pop))
#define SET_FLD_V5(x, m1, v1, m2, v2) \
__pragma(warning(push)) \
__pragma(warning(disable:4244)) \
BM_SET_MASK_FLD(x, m1|m2, MV(m1,v1)| MV(m2,v2)) \
__pragma(warning(pop))
#define SET_FLD_V7(x, m1, v1, m2, v2, m3, v3) \
__pragma(warning(push)) \
__pragma(warning(disable:4244)) \
BM_SET_MASK_FLD(x, m1|m2|m3, MV(m1,v1)| MV(m2,v2)| MV(m3,v3)) \
__pragma(warning(pop))
#define SET_FLD_V9(x, m1, v1, m2, v2, m3, v3, m4, v4) \
__pragma(warning(push)) \
__pragma(warning(disable:4244)) \
BM_SET_MASK_FLD(x, m1|m2|m3|m4, MV(m1,v1)| MV(m2,v2)| MV(m3,v3)| MV(m4,v4)) \
__pragma(warning(pop))
#define SET_FLD_V11(x, m1, v1, m2, v2, m3, v3, m4, v4, m5, v5) \
__pragma(warning(push)) \
__pragma(warning(disable:4244)) \
BM_SET_MASK_FLD(x, m1|m2|m3|m4|m5, MV(m1,v1)| MV(m2,v2)| MV(m3,v3)| MV(m4,v4)| MV(m5,v5)) \
__pragma(warning(pop))
#define SET_FLD_V13(x, m1, v1, m2, v2, m3, v3, m4, v4, m5, v5, m6, v6) \
__pragma(warning(push)) \
__pragma(warning(disable:4244)) \
BM_SET_MASK_FLD(x, m1|m2|m3|m4|m5|m6, MV(m1,v1)| MV(m2,v2)| MV(m3,v3)| MV(m4,v4)| MV(m5,v5)| MV(m6,v6)) \
__pragma(warning(pop))
#endif
#if 0
//! Massage \a x for use in bitfield \a name.
#define BFN_PREP(x, name) ( ((x)<<name##_SHIFT) & name##_MASK )
//! Get the value of bitfield \a name from \a y. Equivalent to (var=) y.name
#define BFN_GET(y, name) ( ((y) & name##_MASK)>>name##_SHIFT )
//! Set bitfield \a name from \a y to \a x: y.name= x.
#define BFN_SET(y, x, name) (y = ((y)&~name##_MASK) | BFN_PREP(x,name) )
// Usage: prio get/set like before:
prio= BFN_GET(attr2, ATTR2_PRIO);
BFN_SET(attr2, x, ATTR2_PRIO);
#endif
+1
View File
@@ -0,0 +1 @@
Packetcraft's dynamic memory allocation
+610
View File
@@ -0,0 +1,610 @@
/*************************************************************************************************/
/*!
* \file my_buf.c
*
* \brief Buffer pool service.
*
* Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved.
*
* Copyright (c) 2019-2020 Packetcraft, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*************************************************************************************************/
#include <buf_pool0/myBuf.h>
#include <buf_pool0/myHeap.h>
#include "types.h"
#include "utility.h"
#include "assert.h"
#include "common\compiler.h"
#include "application\print\printf.h"
/**************************************************************************************************
Global Variables
**************************************************************************************************/
/*! \brief Critical section nesting level. */
_attribute_data_retention_ static u8 myCsNesting = 0;
/*************************************************************************************************/
/*!
* \brief Enter a critical section.
*/
/*************************************************************************************************/
void myCsEnter(void)
{
if (myCsNesting == 0)
{
irq_disable();
}
myCsNesting++;
}
/*************************************************************************************************/
/*!
* \brief Exit a critical section.
*/
/*************************************************************************************************/
void myCsExit(void)
{
assert(myCsNesting != 0);
myCsNesting--;
if (myCsNesting == 0)
{
irq_enable();
}
}
/**************************************************************************************************
Macros
**************************************************************************************************/
#define DEBUG_INFO //printf //debug use
/* Magic number used to check for free buffer. */
#define MY_BUF_FREE_NUM 0xFAABD00D
/**************************************************************************************************
Data Types
**************************************************************************************************/
/* Unit of memory storage-- a structure containing a pointer. */
typedef struct myBufMem_tag
{
struct myBufMem_tag *pNext;
#if MY_BUF_FREE_CHECK_ASSERT == TRUE
u32 free;
#endif
} myBufMem_t;
/* Internal buffer pool. */
typedef struct
{
myBufPoolDesc_t desc; /* Number of buffers and length. */
myBufMem_t *pStart; /* Start of pool. */
myBufMem_t *pFree; /* First free buffer in pool. */
#if MY_BUF_STATS == TRUE
u8 numAlloc; /* Number of buffers currently allocated from pool. */
u8 maxAlloc; /* Maximum buffers ever allocated from pool. */
u16 maxReqLen; /* Maximum request length from pool. */
#endif
} myBufPool_t;
/**************************************************************************************************
Global Variables
**************************************************************************************************/
/* Number of pools. */
_attribute_data_retention_ u8 myBufNumPools;
/* Memory used for pools. */
_attribute_data_retention_ myBufMem_t *myBufMem = NULL;
/* Currently use for debugging only. */
_attribute_data_retention_ u32 myBufMemLen;
#if MY_BUF_STATS_HIST == TRUE
/* Buffer allocation counter. */
_attribute_data_retention_ u8 myBufAllocCount[MY_BUF_STATS_MAX_LEN];
/* Pool Overflow counter. */
_attribute_data_retention_ u8 myPoolOverFlowCount[MY_BUF_STATS_MAX_POOL];
#endif
#if MY_OS_DIAG == TRUE
/* MY buffer diagnostic callback function. */
_attribute_data_retention_ static myBufDiagCback_t myBufDiagCback = NULL;
#endif
/*************************************************************************************************/
/*!
* \brief Calculate size required by the buffer pool.
*
* \param numPools Number of buffer pools.
* \param pDesc Array of buffer pool descriptors, one for each pool.
*
* \return Amount of pBufMem used.
*/
/*************************************************************************************************/
u32 myBufCalcSize(u8 numPools, myBufPoolDesc_t *pDesc)
{
u32 len;
u32 descLen;
myBufPool_t *pPool;
myBufMem_t *pStart;
u8 i;
myBufMem = (myBufMem_t *)0;
pPool = (myBufPool_t *)myBufMem;
/* Buffer storage starts after the pool structs. */
pStart = (myBufMem_t *) (pPool + numPools);
/* Create each pool; see loop exit condition below. */
while (TRUE)
{
/* Exit loop after verification check. */
if (numPools-- == 0)
{
break;
}
/* Adjust pool lengths for minimum size and alignment. */
if (pDesc->len < sizeof(myBufMem_t))
{
descLen = sizeof(myBufMem_t);
}
else if ((pDesc->len % sizeof(myBufMem_t)) != 0)
{
descLen = pDesc->len + sizeof(myBufMem_t) - (pDesc->len % sizeof(myBufMem_t));
}
else
{
descLen = pDesc->len;
}
len = descLen / sizeof(myBufMem_t);
for (i = pDesc->num; i > 0; i--)
{
/* Pointer to the next free buffer is stored in the buffer itself. */
pStart += len;
}
pDesc++;
}
return (u8 *)pStart - (u8 *)myBufMem;
}
/*************************************************************************************************/
/*!
* \brief Initialize the buffer pool service. This function should only be called once
* upon system initialization.
*
* \param numPools Number of buffer pools.
* \param pDesc Array of buffer pool descriptors, one for each pool.
*
* \return Amount of pBufMem used or 0 for failures.
*/
/*************************************************************************************************/
u32 myBufInit(u8 numPools, myBufPoolDesc_t *pDesc)
{
myBufPool_t *pPool;
myBufMem_t *pStart;
u16 len;
u8 i;
myBufMem = (myBufMem_t *) myHeapGetFreeStartAddress();//ȡsystemHeapStartAddr
pPool = (myBufPool_t *) myBufMem;
/* Buffer storage starts after the pool structs. */
pStart = (myBufMem_t *) (pPool + numPools); //ڴͷnumPoolspStartָڴ0ĵһ(num=0)ʼַ
myBufNumPools = numPools;
/* Create each pool; see loop exit condition below. */
while (TRUE)
{
/* Verify we didn't overrun memory; if we did, abort. */
if (pStart > &myBufMem[myHeapCountAvailable() / sizeof(myBufMem_t)])
{
assert(FALSE);
return 0;
}
/* Exit loop after verification check. */
if (numPools-- == 0)
{
break;
}
/* Adjust pool lengths for minimum size and alignment. */
if (pDesc->len < sizeof(myBufMem_t)) //һڴس < sizeof(myBufMem_t)
{
pPool->desc.len = sizeof(myBufMem_t);
}
else if ((pDesc->len % sizeof(myBufMem_t)) != 0)//ȡsizeof(myBufMem_t)ֽڶ
{
pPool->desc.len = pDesc->len + sizeof(myBufMem_t) - (pDesc->len % sizeof(myBufMem_t));
}
else
{
pPool->desc.len = pDesc->len;
}
pPool->desc.num = pDesc->num;
pDesc++;
pPool->pStart = pStart;
pPool->pFree = pStart;
#if MY_BUF_STATS == TRUE
pPool->numAlloc = 0;
pPool->maxAlloc = 0;
pPool->maxReqLen = 0;
#endif
/* Initialize free list. */
len = pPool->desc.len / sizeof(myBufMem_t);
for (i = pPool->desc.num; i > 1; i--)
{
/* Verify we didn't overrun memory; if we did, abort. */
if (pStart > &myBufMem[myHeapCountAvailable() / sizeof(myBufMem_t)])
{
assert(FALSE);
return 0;
}
/* Pointer to the next free buffer is stored in the buffer itself. */
pStart->pNext = pStart + len; //ָһ
pStart += len;//pStartָǰڴصһʼַ(/ǰڴضӦnum++)
}
/* Verify we didn't overrun memory; if we did, abort. */
if (pStart > &myBufMem[myHeapCountAvailable() / sizeof(myBufMem_t)])
{
assert(FALSE);
return 0;
}
/* Last one in list points to NULL. */
pStart->pNext = NULL;//ǰڴصһnumӦһʼַΪNULL
pStart += len;//pStartָһڴصĵһʼַ
/* Next pool. */
pPool++; //ָһڴͷַ
}
myBufMemLen = (u8 *) pStart - (u8 *) myBufMem;
return myBufMemLen; //ڴ0ڴnumPools-1ȫʼĵBufferСλByte
}
/*************************************************************************************************/
/*!
* \brief Allocate a buffer.
*
* \param len Length of buffer to allocate.
*
* \return Pointer to allocated buffer or NULL if allocation fails.
*/
/*************************************************************************************************/
void *myBufAlloc(u16 len)
{
myBufPool_t *pPool;
myBufMem_t *pBuf;
u8 i;
//MY_CS_INIT(cs);
assert(len > 0);
pPool = (myBufPool_t *) myBufMem;
for (i = myBufNumPools; i > 0; i--, pPool++)
{
/* Check if buffer is big enough. */
if (len <= pPool->desc.len)
{
/* Enter critical section. */
myCsEnter();
/* Check if buffers are available. */
if (pPool->pFree != NULL)
{
/* Allocation succeeded. */
pBuf = pPool->pFree;
/* Next free buffer is stored inside current free buffer. */
pPool->pFree = pBuf->pNext;
#if MY_BUF_FREE_CHECK_ASSERT == TRUE
pBuf->free = 0;
#endif
#if MY_BUF_STATS_HIST == TRUE
/* Increment count for buffers of this length. */
if (len < MY_BUF_STATS_MAX_LEN)
{
myBufAllocCount[len]++;
}
else
{
myBufAllocCount[0]++;
}
#endif
#if MY_BUF_STATS == TRUE
if (++pPool->numAlloc > pPool->maxAlloc)
{
pPool->maxAlloc = pPool->numAlloc;
}
pPool->maxReqLen = max2(pPool->maxReqLen, len);
#endif
/* Exit critical section. */
myCsExit();;
return pBuf;
}
#if MY_BUF_STATS_HIST == TRUE
else
{
/* Pool overflow: increment count of overflow for current pool. */
myPoolOverFlowCount[myBufNumPools-i]++;
}
#endif
/* Exit critical section. */
myCsExit();;
#if MY_BUF_ALLOC_BEST_FIT_FAIL_ASSERT == TRUE
assert(FALSE);
#endif
}
}
/* Allocation failed. */
#if MY_OS_DIAG == TRUE
if (myBufDiagCback != NULL)
{
myBufDiag_t info;
info.type = MY_BUF_ALLOC_FAILED;
info.param.alloc.taskId = MY_OS_GET_ACTIVE_HANDLER_ID();
info.param.alloc.len = len;
myBufDiagCback(&info);
}
else
{
}
#else
#endif
#if MY_BUF_ALLOC_FAIL_ASSERT == TRUE
assert(FALSE);
#endif
return NULL;
}
/*************************************************************************************************/
/*!
* \brief Free a buffer.
*
* \param pBuf Buffer to free.
*/
/*************************************************************************************************/
void myBufFree(void *pBuf)
{
myBufPool_t *pPool;
myBufMem_t *p = pBuf;
//MY_CS_INIT(cs);
/* Verify pointer is within range. */
#if MY_BUF_FREE_CHECK_ASSERT == TRUE
assert(p >= ((myBufPool_t *) myBufMem)->pStart);
assert(p < (myBufMem_t *)(((u8 *) myBufMem) + myBufMemLen));
#endif
/* Iterate over pools starting from last pool. */
pPool = (myBufPool_t *) myBufMem + (myBufNumPools - 1);
while (pPool >= (myBufPool_t *) myBufMem)
{
/* Check if the buffer memory is located inside this pool. */
if (p >= pPool->pStart)
{
/* Enter critical section. */
myCsEnter();
#if MY_BUF_FREE_CHECK_ASSERT == TRUE
assert(p->free != MY_BUF_FREE_NUM);
p->free = MY_BUF_FREE_NUM;
#endif
#if MY_BUF_STATS == TRUE
pPool->numAlloc--;
#endif
/* Pool found; put buffer back in free list. */
p->pNext = pPool->pFree;
pPool->pFree = p;
/* Exit critical section. */
myCsExit();;
return;
}
/* Next pool. */
pPool--;
}
/* Should never get here. */
assert(FALSE);
return;
}
/*************************************************************************************************/
/*!
* \brief Diagnostic function to get the buffer allocation statistics.
*
* \return Buffer allocation statistics array.
*/
/*************************************************************************************************/
u8 *myBufGetAllocStats(void)
{
#if MY_BUF_STATS_HIST == TRUE
return myBufAllocCount;
#else
return NULL;
#endif
}
/*************************************************************************************************/
/*!
* \brief Diagnostic function to get the number of overflow times for each pool.
*
* \return Overflow times statistics array
*/
/*************************************************************************************************/
u8 *myBufGetPoolOverFlowStats(void)
{
#if MY_BUF_STATS_HIST == TRUE
return myPoolOverFlowCount;
#else
return NULL;
#endif
}
/*************************************************************************************************/
/*!
* \brief Get number of pools.
*
* \return Number of pools.
*/
/*************************************************************************************************/
u8 myBufGetNumPool(void)
{
return myBufNumPools;
}
/*************************************************************************************************/
/*!
* \brief Get statistics for each pool.
*
* \param pBuf Buffer to store the statistics.
* \param poolId Pool ID.
*/
/*************************************************************************************************/
void myBufGetPoolStats(myBufPoolStat_t *pStat, u8 poolId)
{
myBufPool_t *pPool;
if (poolId >= myBufNumPools)
{
pStat->bufSize = 0;
return;
}
//MY_CS_INIT(cs);
myCsEnter();
pPool = (myBufPool_t *) myBufMem;
pStat->bufSize = pPool[poolId].desc.len;
pStat->numBuf = pPool[poolId].desc.num;
#if MY_BUF_STATS == TRUE
pStat->numAlloc = pPool[poolId].numAlloc;
pStat->maxAlloc = pPool[poolId].maxAlloc;
pStat->maxReqLen = pPool[poolId].maxReqLen;
#else
pStat->numAlloc = 0;
pStat->maxAlloc = 0;
pStat->maxReqLen = 0;
#endif
/* Exit critical section. */
myCsExit();;
}
/*************************************************************************************************/
/*!
* \brief Called to register the buffer diagnostics callback function.
*
* \param pCallback Pointer to the callback function.
*/
/*************************************************************************************************/
void myBufDiagRegister(myBufDiagCback_t callback)
{
#if MY_OS_DIAG == TRUE
myBufDiagCback = callback;
#else
/* Unused parameter */
(void)callback;
#endif
}
#if 0 //demo test
u8* AAA = NULL;
u8* ABB = NULL;
u8* ACC = NULL;
u8* ADD = NULL;
u8* AEE = NULL;
u8* AFF = NULL;
u8* AGG = NULL;
myBufPoolStat_t myBufPoolStatA,myBufPoolStatB,myBufPoolStatC;
void user_init(void)
{
myBufPoolDesc_t poolDesc[] =
{
{ 16, 8 },
{ 32, 4 },
{ 64, 8 },
{ 128, 4 },
{ 256, 4 },
{ 512, 2 },
};
const u8 numPools = sizeof(poolDesc) / sizeof(poolDesc[0]);
/* Initial buffer configuration. */
u16 memUsed = myBufInit(numPools, poolDesc);
myHeapAlloc(memUsed);
AAA = myBufAlloc(512);
ABB = myBufAlloc(19);
ACC = myBufAlloc(45);
ADD = myBufAlloc(6);
AEE = myBufAlloc(36);
AFF = myBufAlloc(97);
AGG = myBufAlloc(78);
myBufFree(AAA);
myBufFree(ABB);
myBufFree(ACC);
myBufFree(ADD);
myBufFree(AEE);
myBufFree(AFF);
myBufFree(AGG);
myBufGetPoolStats(&myBufPoolStatA, 1);
myBufGetPoolStats(&myBufPoolStatB, 2);
myBufGetPoolStats(&myBufPoolStatC, 5);
}
#endif
+236
View File
@@ -0,0 +1,236 @@
/*************************************************************************************************/
/*!
* \file my_buf.h
*
* \brief Buffer pool service.
*
* Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved.
*
* Copyright (c) 2019-2020 Packetcraft, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*************************************************************************************************/
#ifndef MY_BUF_H
#define MY_BUF_H
#ifdef __cplusplus
extern "C" {
#endif
#include "common/types.h"
#include "common/compiler.h"
/*! \addtogroup MY_BUF_API
* \{ */
/**************************************************************************************************
Configuration
**************************************************************************************************/
/*! \brief Check if trying to free a buffer that is already free */
#ifndef MY_BUF_FREE_CHECK_ASSERT
#define MY_BUF_FREE_CHECK_ASSERT TRUE
#endif
/*! \brief Assert on best-fit buffer allocation failure */
#ifndef MY_BUF_ALLOC_BEST_FIT_FAIL_ASSERT
#define MY_BUF_ALLOC_BEST_FIT_FAIL_ASSERT TRUE//FALSE
#endif
/*! \brief Assert on buffer allocation failure */
#ifndef MY_BUF_ALLOC_FAIL_ASSERT
#define MY_BUF_ALLOC_FAIL_ASSERT TRUE
#endif
/*! \brief Buffer histogram stats */
#ifndef MY_BUF_STATS_HIST
#define MY_BUF_STATS_HIST FALSE//TRUE//
#endif
/**************************************************************************************************
Macros
**************************************************************************************************/
/*! \brief Length of the buffer statistics array */
#define MY_BUF_STATS_MAX_LEN 128
/*! \brief Max number of pools can allocate */
#define MY_BUF_STATS_MAX_POOL 32
/*! \brief Failure Codes */
#define MY_BUF_ALLOC_FAILED 1
#ifndef MY_BUF_STATS
/*! \brief Enable buffer allocation statistics. */
#define MY_BUF_STATS FALSE//TRUE//
#endif
/**************************************************************************************************
Data Types
**************************************************************************************************/
/*! \brief Buffer pool descriptor structure */
typedef struct
{
u16 len; /*!< \brief Length of buffers in pool */
u8 num; /*!< \brief Number of buffers in pool */
} myBufPoolDesc_t;
/*! \brief Pool statistics */
typedef struct
{
u16 bufSize; /*!< \brief Pool buffer size. */
u8 numBuf; /*!< \brief Total number of buffers. */
u8 numAlloc; /*!< \brief Number of outstanding allocations. */
u8 maxAlloc; /*!< \brief High allocation watermark. */
u16 maxReqLen; /*!< \brief Maximum requested buffer length. */
} myBufPoolStat_t;
/*! \brief MY buffer diagnostics - buffer allocation failure */
typedef struct
{
u8 taskId; /*!< \brief Task handler ID where failure occured */
u16 len; /*!< \brief Length of buffer being allocated */
} myBufDiagAllocFail_t;
/*! \brief MY buffer diagnostics message */
typedef struct
{
union
{
myBufDiagAllocFail_t alloc; /*!< \brief Buffer allocation failure */
} param; /*!< \brief Union of diagnostic data types. */
u8 type; /*!< \brief Type of error */
} myBufDiag_t;
/**************************************************************************************************
Callback Function Datatypes
**************************************************************************************************/
/*************************************************************************************************/
/*!
* \brief Callback providing MY buffer diagnostic messages.
*
* \param pInfo Diagnostics message.
*/
/*************************************************************************************************/
typedef void (*myBufDiagCback_t)(myBufDiag_t *pInfo);
/**************************************************************************************************
Function Declarations
**************************************************************************************************/
/*************************************************************************************************/
/*!
* \brief Calculate size required by the buffer pool.
*
* \param numPools Number of buffer pools.
* \param pDesc Array of buffer pool descriptors, one for each pool.
*
* \return Amount of pBufMem used.
*/
/*************************************************************************************************/
u32 myBufCalcSize(u8 numPools, myBufPoolDesc_t *pDesc);
/*************************************************************************************************/
/*!
* \brief Initialize the buffer pool service. This function should only be called once
* upon system initialization.
*
* \param numPools Number of buffer pools.
* \param pDesc Array of buffer pool descriptors, one for each pool.
*
* \return Amount of pBufMem used or 0 for failures.
*/
/*************************************************************************************************/
u32 myBufInit(u8 numPools, myBufPoolDesc_t *pDesc);
/*************************************************************************************************/
/*!
* \brief Allocate a buffer.
*
* \param len Length of buffer to allocate.
*
* \return Pointer to allocated buffer or NULL if allocation fails.
*/
/*************************************************************************************************/
void *myBufAlloc(u16 len);
/*************************************************************************************************/
/*!
* \brief Free a buffer.
*
* \param pBuf Buffer to free.
*/
/*************************************************************************************************/
void myBufFree(void *pBuf);
/*************************************************************************************************/
/*!
* \brief Diagnostic function to get the buffer allocation statistics.
*
* \return Buffer allocation statistics array.
*/
/*************************************************************************************************/
u8 *myBufGetAllocStats(void);
/*************************************************************************************************/
/*!
* \brief Diagnostic function to get the number of overflow times for each pool.
*
* \return Overflow times statistics array
*/
/*************************************************************************************************/
u8 *myBufGetPoolOverFlowStats(void);
/*************************************************************************************************/
/*!
* \brief Get number of pools.
*
* \return Number of pools.
*/
/*************************************************************************************************/
u8 myBufGetNumPool(void);
/*************************************************************************************************/
/*!
* \brief Get statistics for each pool.
*
* \param pStat Buffer to store the statistics.
* \param numPool Number of pool elements.
*
* \return Pool statistics.
*/
/*************************************************************************************************/
void myBufGetPoolStats(myBufPoolStat_t *pStat, u8 numPool);
/*************************************************************************************************/
/*!
* \brief Called to register the buffer diagnostics callback function.
*
* \param callback Pointer to the callback function.
*/
/*************************************************************************************************/
void myBufDiagRegister(myBufDiagCback_t callback);
/*! \} */ /* MY_BUF_API */
#ifdef __cplusplus
};
#endif
#endif /* MY_BUF_H */
+94
View File
@@ -0,0 +1,94 @@
/*************************************************************************************************/
/*!
* \file my_heap.c
*
* \brief Heap service.
*
* Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved.
*
* Copyright (c) 2019-2020 Packetcraft, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*************************************************************************************************/
#include "common\types.h"
#include "common\compiler.h"
/**************************************************************************************************
Macros
**************************************************************************************************/
#define HEAP_MEM_SIZE_CFG 3072 //3K Heap
/**************************************************************************************************
Global Variables
**************************************************************************************************/
/*! Free memory for pool buffers. */
_attribute_data_retention_ static u8 myBufMem[HEAP_MEM_SIZE_CFG];
_attribute_data_retention_ static u8 *SystemHeapStart = myBufMem;
_attribute_data_retention_ static u32 SystemHeapSize = HEAP_MEM_SIZE_CFG;
/*************************************************************************************************/
/*!
* \brief Reserve heap memory.
*
* \param size Number of bytes of heap memory used.
*/
/*************************************************************************************************/
void myHeapAlloc(u32 size)
{
/* Round up to nearest multiple of 4 for word alignment */
size = (size + 3) & ~3;
SystemHeapStart += size;
SystemHeapSize -= size;
}
/*************************************************************************************************/
/*!
* \brief Get next available heap memory.
*
* \return Address of the start of heap memory.
*/
/*************************************************************************************************/
void *myHeapGetFreeStartAddress(void)
{
return (void *)SystemHeapStart;
}
/*************************************************************************************************/
/*!
* \brief Get heap available.
*
* \return Number of bytes of heap memory available.
*/
/*************************************************************************************************/
u32 myHeapCountAvailable(void)
{
return SystemHeapSize;
}
/*************************************************************************************************/
/*!
* \brief Get heap used.
*
* \return Number of bytes of heap memory used.
*/
/*************************************************************************************************/
u32 myHeapCountUsed(void)
{
return HEAP_MEM_SIZE_CFG - SystemHeapSize;
}
+84
View File
@@ -0,0 +1,84 @@
/*************************************************************************************************/
/*!
* \file my_heap.h
*
* \brief Buffer heap service.
*
* Copyright (c) 2018 Arm Ltd. All Rights Reserved.
*
* Copyright (c) 2019-2020 Packetcraft, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*************************************************************************************************/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/*! \addtogroup MY_HEAP_API
* \{ */
#include "common/types.h"
#include "common/compiler.h"
/*************************************************************************************************/
/*!
* \brief Get heap available.
*
* \return Number of bytes of heap memory available.
*/
/*************************************************************************************************/
u32 myHeapCountAvailable(void);
/*************************************************************************************************/
/*!
* \brief Get heap used.
*
* \return Number of bytes of heap memory used.
*/
/*************************************************************************************************/
u32 myHeapCountUsed(void);
/*************************************************************************************************/
/*!
* \brief Reserve heap memory.
*
* \param size Number of bytes of heap memory used.
*/
/*************************************************************************************************/
void myHeapAlloc(u32 size);
/*************************************************************************************************/
/*!
* \brief Get next available heap memory.
*
* \return Address of the start of heap memory.
*/
/*************************************************************************************************/
void *myHeapGetFreeStartAddress(void);
/*! \} */ /* MY_HEAP_API */
#ifdef __cplusplus
};
#endif

Some files were not shown because too many files have changed in this diff Show More